@shival99/z-ui 1.4.7 → 1.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/shival99-z-ui-providers.mjs +35 -3
- package/fesm2022/shival99-z-ui-providers.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-services.mjs +94 -79
- package/fesm2022/shival99-z-ui-services.mjs.map +1 -1
- package/package.json +1 -1
- package/types/shival99-z-ui-components-z-calendar.d.ts +4 -4
- package/types/shival99-z-ui-components-z-editor.d.ts +1 -1
- package/types/shival99-z-ui-components-z-input.d.ts +2 -2
- package/types/shival99-z-ui-components-z-modal.d.ts +1 -1
- package/types/shival99-z-ui-components-z-select.d.ts +1 -1
- package/types/shival99-z-ui-components-z-upload.d.ts +3 -3
- package/types/shival99-z-ui-providers.d.ts +23 -2
- package/types/shival99-z-ui-services.d.ts +34 -52
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { InjectionToken, makeEnvironmentProviders, inject, provideAppInitializer } from '@angular/core';
|
|
2
|
-
import {
|
|
1
|
+
import { InjectionToken, makeEnvironmentProviders, provideEnvironmentInitializer, inject, provideAppInitializer } from '@angular/core';
|
|
2
|
+
import { ZCacheService, ZIndexDbService, Z_THEME_CONFIG, Z_LANG_CACHE_KEY } from '@shival99/z-ui/services';
|
|
3
3
|
import { provideEnvironmentNgxMask } from 'ngx-mask';
|
|
4
4
|
import { provideScrollbarOptions } from 'ngx-scrollbar';
|
|
5
5
|
import { HttpClient } from '@angular/common/http';
|
|
@@ -8,6 +8,38 @@ import { Z_UI_TRANSLATIONS } from '@shival99/z-ui/i18n';
|
|
|
8
8
|
import { of, forkJoin, map, firstValueFrom } from 'rxjs';
|
|
9
9
|
import { catchError } from 'rxjs/operators';
|
|
10
10
|
|
|
11
|
+
/** Injection token for ZCacheService configuration */
|
|
12
|
+
const Z_CACHE_CONFIG = new InjectionToken('Z_CACHE_CONFIG');
|
|
13
|
+
/**
|
|
14
|
+
* Provide Z-Cache service with configuration
|
|
15
|
+
* @param config - Cache configuration with prefix and encrypt options
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* // In app.config.ts
|
|
20
|
+
* export const appConfig: ApplicationConfig = {
|
|
21
|
+
* providers: [
|
|
22
|
+
* provideZCache({
|
|
23
|
+
* prefix: 'myapp_',
|
|
24
|
+
* encrypt: false, // Disable encryption for debugging
|
|
25
|
+
* }),
|
|
26
|
+
* ],
|
|
27
|
+
* };
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
function provideZCache(config = {}) {
|
|
31
|
+
return makeEnvironmentProviders([
|
|
32
|
+
{
|
|
33
|
+
provide: Z_CACHE_CONFIG,
|
|
34
|
+
useValue: config,
|
|
35
|
+
},
|
|
36
|
+
provideEnvironmentInitializer(() => {
|
|
37
|
+
const cacheConfig = inject(Z_CACHE_CONFIG);
|
|
38
|
+
ZCacheService.configure(cacheConfig);
|
|
39
|
+
}),
|
|
40
|
+
]);
|
|
41
|
+
}
|
|
42
|
+
|
|
11
43
|
/** Injection token for ZIndexDbService */
|
|
12
44
|
const Z_INDEXDB_SERVICE = new InjectionToken('ZIndexDbService');
|
|
13
45
|
/**
|
|
@@ -183,5 +215,5 @@ function provideZTranslate(config = {}) {
|
|
|
183
215
|
* Generated bundle index. Do not edit.
|
|
184
216
|
*/
|
|
185
217
|
|
|
186
|
-
export { Z_INDEXDB_SERVICE, provideZIndexDb, provideZNgxMask, provideZScrollbar, provideZTheme, provideZTranslate, zCreateTranslateLoader };
|
|
218
|
+
export { Z_CACHE_CONFIG, Z_INDEXDB_SERVICE, provideZCache, provideZIndexDb, provideZNgxMask, provideZScrollbar, provideZTheme, provideZTranslate, zCreateTranslateLoader };
|
|
187
219
|
//# sourceMappingURL=shival99-z-ui-providers.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shival99-z-ui-providers.mjs","sources":["../../../../libs/core-ui/providers/z-indexdb.provider.ts","../../../../libs/core-ui/providers/z-ngx-mask.provider.ts","../../../../libs/core-ui/providers/z-scrollbar.provider.ts","../../../../libs/core-ui/providers/z-theme.provider.ts","../../../../libs/core-ui/providers/z-translate.provider.ts","../../../../libs/core-ui/providers/types/z-ngx-mask.types.ts","../../../../libs/core-ui/providers/shival99-z-ui-providers.ts"],"sourcesContent":["import { type EnvironmentProviders, InjectionToken, makeEnvironmentProviders } from '@angular/core';\nimport { type ZIndexDbConfig, ZIndexDbService } from '@shival99/z-ui/services';\n\n/** Injection token for ZIndexDbService */\nexport const Z_INDEXDB_SERVICE = new InjectionToken<ZIndexDbService>('ZIndexDbService');\n\n/**\n * Provide Z-IndexDB service with configuration\n * @param config - IndexDB configuration with multi-store support\n *\n * @example\n * ```typescript\n * // In app.config.ts\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideZIndexDb({\n * dbName: 'MyApp',\n * version: 1,\n * stores: [\n * { name: 'cache', encrypt: true },\n * { name: 'userData', encrypt: true, protectedKeys: ['profile'] },\n * { name: 'settings', encrypt: false },\n * ],\n * defaultStore: 'cache',\n * protectedKeys: ['token'],\n * }),\n * ],\n * };\n * ```\n */\nexport function provideZIndexDb(config: ZIndexDbConfig = {}): EnvironmentProviders {\n return makeEnvironmentProviders([\n {\n provide: Z_INDEXDB_SERVICE,\n useFactory: () => new ZIndexDbService(config),\n },\n {\n provide: ZIndexDbService,\n useExisting: Z_INDEXDB_SERVICE,\n },\n ]);\n}\n","import { type EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { ZCacheService } from '@shival99/z-ui/services';\nimport { provideEnvironmentNgxMask } from 'ngx-mask';\nimport type { ZNgxMaskConfig } from './types/z-ngx-mask.types';\n\nconst LANG_CACHE_KEY = 'Z_LANGUAGE';\n\n/**\n * Get locale-specific mask configuration\n */\nfunction getMaskConfig(lang: string, config: ZNgxMaskConfig = {}) {\n const isVietnamese = lang === 'vi';\n\n return {\n validation: config.validation ?? true,\n thousandSeparator: isVietnamese ? ',' : '.',\n decimalMarker: (isVietnamese ? '.' : ',') as '.' | ',',\n allowNegativeNumbers: config.allowNegativeNumbers ?? true,\n };\n}\n\n/**\n * Provide Z-NgxMask with locale-aware configuration\n * @param config - Mask configuration\n *\n * @example\n * ```typescript\n * // In app.config.ts\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideZNgxMask({ lang: 'vi' }),\n * ],\n * };\n * ```\n */\nexport function provideZNgxMask(config: ZNgxMaskConfig = {}): EnvironmentProviders {\n const savedLang = typeof window !== 'undefined' ? ZCacheService.get<string>(LANG_CACHE_KEY) : null;\n const lang = config.lang ?? savedLang ?? 'vi';\n const maskConfig = getMaskConfig(lang, config);\n\n return makeEnvironmentProviders([provideEnvironmentNgxMask(maskConfig)]);\n}\n","import { type EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { provideScrollbarOptions } from 'ngx-scrollbar';\n\n/**\n * Provides global scrollbar options for ngx-scrollbar\n * Use this in app.config.ts: providers: [provideZScrollbar()]\n */\nexport function provideZScrollbar(): EnvironmentProviders {\n return makeEnvironmentProviders([\n provideScrollbarOptions({\n visibility: 'hover',\n appearance: 'compact',\n withButtons: false,\n sensorThrottleTime: 200,\n }),\n ]);\n}\n","import { makeEnvironmentProviders, type EnvironmentProviders } from '@angular/core';\nimport { type ZThemeConfig, Z_THEME_CONFIG } from '@shival99/z-ui/services';\n\n/**\n * Provide theme configuration for the application\n * @param config - Theme configuration with defaultTheme and defaultDarkMode\n * @example\n * ```typescript\n * // In app.config.ts\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideZTheme({ defaultTheme: 'hospital', defaultDarkMode: false })\n * ]\n * };\n * ```\n */\nexport function provideZTheme(config: ZThemeConfig = {}): EnvironmentProviders {\n return makeEnvironmentProviders([{ provide: Z_THEME_CONFIG, useValue: config }]);\n}\n","/* eslint-disable @stylistic/indent */\nimport { HttpClient } from '@angular/common/http';\nimport { inject, makeEnvironmentProviders, provideAppInitializer, type EnvironmentProviders } from '@angular/core';\nimport {\n provideTranslateService,\n TranslateLoader,\n TranslateService,\n type TranslationObject,\n} from '@ngx-translate/core';\nimport { Z_UI_TRANSLATIONS, type ZUITranslations } from '@shival99/z-ui/i18n';\nimport { Z_LANG_CACHE_KEY, ZCacheService } from '@shival99/z-ui/services';\nimport { firstValueFrom, forkJoin, map, type Observable, of } from 'rxjs';\nimport { catchError } from 'rxjs/operators';\nimport type { ZTranslateProviderConfig } from './types/z-translate.types';\n\nclass ZTranslateHttpLoader implements TranslateLoader {\n public constructor(\n private readonly _http: HttpClient,\n private readonly _prefix: string,\n private readonly _suffix: string,\n private readonly _includeZUI: boolean,\n private readonly _zuiOverridePath?: string,\n private readonly _customZUI?: Partial<Record<string, ZUITranslations>>\n ) {}\n\n public getTranslation(lang: string): Observable<TranslationObject> {\n const userTranslations$ = this._http\n .get<TranslationObject>(`${this._prefix}${lang}${this._suffix}`)\n .pipe(catchError(() => of({} as TranslationObject)));\n\n if (!this._includeZUI) {\n return userTranslations$;\n }\n\n const zuiDefaults = Z_UI_TRANSLATIONS[lang] ?? Z_UI_TRANSLATIONS['en'] ?? {};\n const zuiFileOverrides$ = this._zuiOverridePath\n ? this._http\n .get<ZUITranslations>(`${this._zuiOverridePath}${lang}${this._suffix}`)\n .pipe(catchError(() => of({} as ZUITranslations)))\n : of({} as ZUITranslations);\n\n const inlineOverrides = this._customZUI?.[lang] ?? {};\n\n return forkJoin([of(zuiDefaults), zuiFileOverrides$, userTranslations$]).pipe(\n map(\n ([defaults, fileOverrides, user]) =>\n ({\n ...defaults,\n ...fileOverrides,\n ...inlineOverrides,\n ...(user as Record<string, unknown>),\n }) as TranslationObject\n )\n );\n }\n}\n\nexport function zCreateTranslateLoader(\n http: HttpClient,\n path = './assets/i18n/',\n extension = '.json',\n includeZUI = true,\n zuiOverridePath?: string,\n customZUI?: Partial<Record<string, ZUITranslations>>\n): TranslateLoader {\n return new ZTranslateHttpLoader(http, path, extension, includeZUI, zuiOverridePath, customZUI);\n}\n\nfunction initializeTranslate(defaultLang: string): Promise<unknown> {\n const translate = inject(TranslateService);\n const savedLang = ZCacheService.get<string>(Z_LANG_CACHE_KEY) ?? defaultLang;\n translate.setFallbackLang(defaultLang);\n return firstValueFrom(translate.use(savedLang));\n}\n\nexport function provideZTranslate(config: ZTranslateProviderConfig = {}): EnvironmentProviders {\n const {\n defaultLang = 'vi',\n translationPath = './assets/i18n/',\n fileExtension = '.json',\n includeZUITranslations = true,\n zuiOverridePath,\n customZUITranslations,\n } = config;\n\n return makeEnvironmentProviders([\n provideTranslateService({\n fallbackLang: defaultLang,\n loader: {\n provide: TranslateLoader,\n useFactory: (http: HttpClient) =>\n zCreateTranslateLoader(\n http,\n translationPath,\n fileExtension,\n includeZUITranslations,\n zuiOverridePath,\n customZUITranslations\n ),\n deps: [HttpClient],\n },\n }),\n provideAppInitializer(() => initializeTranslate(defaultLang)),\n ]);\n}\n\nexport { Z_UI_TRANSLATIONS, mergeTranslations, getZUITranslations } from '@shival99/z-ui/i18n';\nexport type { ZUITranslations, ZUILanguage, ZUITranslationSet } from '@shival99/z-ui/i18n';\n","/**\n * Z-NgxMask Provider Types\n */\n\nexport interface ZNgxMaskConfig {\n /** Language code (vi, en, etc.) */\n lang?: string;\n /** Allow negative numbers */\n allowNegativeNumbers?: boolean;\n /** Enable validation */\n validation?: boolean;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shival99-z-ui-providers.mjs","sources":["../../../../libs/core-ui/providers/z-cache.provider.ts","../../../../libs/core-ui/providers/z-indexdb.provider.ts","../../../../libs/core-ui/providers/z-ngx-mask.provider.ts","../../../../libs/core-ui/providers/z-scrollbar.provider.ts","../../../../libs/core-ui/providers/z-theme.provider.ts","../../../../libs/core-ui/providers/z-translate.provider.ts","../../../../libs/core-ui/providers/types/z-ngx-mask.types.ts","../../../../libs/core-ui/providers/shival99-z-ui-providers.ts"],"sourcesContent":["import {\n type EnvironmentProviders,\n inject,\n InjectionToken,\n makeEnvironmentProviders,\n provideEnvironmentInitializer,\n} from '@angular/core';\nimport { type ZCacheConfig, ZCacheService } from '@shival99/z-ui/services';\n\n/** Injection token for ZCacheService configuration */\nexport const Z_CACHE_CONFIG = new InjectionToken<ZCacheConfig>('Z_CACHE_CONFIG');\n\n/**\n * Provide Z-Cache service with configuration\n * @param config - Cache configuration with prefix and encrypt options\n *\n * @example\n * ```typescript\n * // In app.config.ts\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideZCache({\n * prefix: 'myapp_',\n * encrypt: false, // Disable encryption for debugging\n * }),\n * ],\n * };\n * ```\n */\nexport function provideZCache(config: ZCacheConfig = {}): EnvironmentProviders {\n return makeEnvironmentProviders([\n {\n provide: Z_CACHE_CONFIG,\n useValue: config,\n },\n provideEnvironmentInitializer(() => {\n const cacheConfig = inject(Z_CACHE_CONFIG);\n ZCacheService.configure(cacheConfig);\n }),\n ]);\n}\n","import { type EnvironmentProviders, InjectionToken, makeEnvironmentProviders } from '@angular/core';\nimport { type ZIndexDbConfig, ZIndexDbService } from '@shival99/z-ui/services';\n\n/** Injection token for ZIndexDbService */\nexport const Z_INDEXDB_SERVICE = new InjectionToken<ZIndexDbService>('ZIndexDbService');\n\n/**\n * Provide Z-IndexDB service with configuration\n * @param config - IndexDB configuration with multi-store support\n *\n * @example\n * ```typescript\n * // In app.config.ts\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideZIndexDb({\n * dbName: 'MyApp',\n * version: 1,\n * stores: [\n * { name: 'cache', encrypt: true },\n * { name: 'userData', encrypt: true, protectedKeys: ['profile'] },\n * { name: 'settings', encrypt: false },\n * ],\n * defaultStore: 'cache',\n * protectedKeys: ['token'],\n * }),\n * ],\n * };\n * ```\n */\nexport function provideZIndexDb(config: ZIndexDbConfig = {}): EnvironmentProviders {\n return makeEnvironmentProviders([\n {\n provide: Z_INDEXDB_SERVICE,\n useFactory: () => new ZIndexDbService(config),\n },\n {\n provide: ZIndexDbService,\n useExisting: Z_INDEXDB_SERVICE,\n },\n ]);\n}\n","import { type EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { ZCacheService } from '@shival99/z-ui/services';\nimport { provideEnvironmentNgxMask } from 'ngx-mask';\nimport type { ZNgxMaskConfig } from './types/z-ngx-mask.types';\n\nconst LANG_CACHE_KEY = 'Z_LANGUAGE';\n\n/**\n * Get locale-specific mask configuration\n */\nfunction getMaskConfig(lang: string, config: ZNgxMaskConfig = {}) {\n const isVietnamese = lang === 'vi';\n\n return {\n validation: config.validation ?? true,\n thousandSeparator: isVietnamese ? ',' : '.',\n decimalMarker: (isVietnamese ? '.' : ',') as '.' | ',',\n allowNegativeNumbers: config.allowNegativeNumbers ?? true,\n };\n}\n\n/**\n * Provide Z-NgxMask with locale-aware configuration\n * @param config - Mask configuration\n *\n * @example\n * ```typescript\n * // In app.config.ts\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideZNgxMask({ lang: 'vi' }),\n * ],\n * };\n * ```\n */\nexport function provideZNgxMask(config: ZNgxMaskConfig = {}): EnvironmentProviders {\n const savedLang = typeof window !== 'undefined' ? ZCacheService.get<string>(LANG_CACHE_KEY) : null;\n const lang = config.lang ?? savedLang ?? 'vi';\n const maskConfig = getMaskConfig(lang, config);\n\n return makeEnvironmentProviders([provideEnvironmentNgxMask(maskConfig)]);\n}\n","import { type EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { provideScrollbarOptions } from 'ngx-scrollbar';\n\n/**\n * Provides global scrollbar options for ngx-scrollbar\n * Use this in app.config.ts: providers: [provideZScrollbar()]\n */\nexport function provideZScrollbar(): EnvironmentProviders {\n return makeEnvironmentProviders([\n provideScrollbarOptions({\n visibility: 'hover',\n appearance: 'compact',\n withButtons: false,\n sensorThrottleTime: 200,\n }),\n ]);\n}\n","import { makeEnvironmentProviders, type EnvironmentProviders } from '@angular/core';\nimport { type ZThemeConfig, Z_THEME_CONFIG } from '@shival99/z-ui/services';\n\n/**\n * Provide theme configuration for the application\n * @param config - Theme configuration with defaultTheme and defaultDarkMode\n * @example\n * ```typescript\n * // In app.config.ts\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideZTheme({ defaultTheme: 'hospital', defaultDarkMode: false })\n * ]\n * };\n * ```\n */\nexport function provideZTheme(config: ZThemeConfig = {}): EnvironmentProviders {\n return makeEnvironmentProviders([{ provide: Z_THEME_CONFIG, useValue: config }]);\n}\n","/* eslint-disable @stylistic/indent */\nimport { HttpClient } from '@angular/common/http';\nimport { inject, makeEnvironmentProviders, provideAppInitializer, type EnvironmentProviders } from '@angular/core';\nimport {\n provideTranslateService,\n TranslateLoader,\n TranslateService,\n type TranslationObject,\n} from '@ngx-translate/core';\nimport { Z_UI_TRANSLATIONS, type ZUITranslations } from '@shival99/z-ui/i18n';\nimport { Z_LANG_CACHE_KEY, ZCacheService } from '@shival99/z-ui/services';\nimport { firstValueFrom, forkJoin, map, type Observable, of } from 'rxjs';\nimport { catchError } from 'rxjs/operators';\nimport type { ZTranslateProviderConfig } from './types/z-translate.types';\n\nclass ZTranslateHttpLoader implements TranslateLoader {\n public constructor(\n private readonly _http: HttpClient,\n private readonly _prefix: string,\n private readonly _suffix: string,\n private readonly _includeZUI: boolean,\n private readonly _zuiOverridePath?: string,\n private readonly _customZUI?: Partial<Record<string, ZUITranslations>>\n ) {}\n\n public getTranslation(lang: string): Observable<TranslationObject> {\n const userTranslations$ = this._http\n .get<TranslationObject>(`${this._prefix}${lang}${this._suffix}`)\n .pipe(catchError(() => of({} as TranslationObject)));\n\n if (!this._includeZUI) {\n return userTranslations$;\n }\n\n const zuiDefaults = Z_UI_TRANSLATIONS[lang] ?? Z_UI_TRANSLATIONS['en'] ?? {};\n const zuiFileOverrides$ = this._zuiOverridePath\n ? this._http\n .get<ZUITranslations>(`${this._zuiOverridePath}${lang}${this._suffix}`)\n .pipe(catchError(() => of({} as ZUITranslations)))\n : of({} as ZUITranslations);\n\n const inlineOverrides = this._customZUI?.[lang] ?? {};\n\n return forkJoin([of(zuiDefaults), zuiFileOverrides$, userTranslations$]).pipe(\n map(\n ([defaults, fileOverrides, user]) =>\n ({\n ...defaults,\n ...fileOverrides,\n ...inlineOverrides,\n ...(user as Record<string, unknown>),\n }) as TranslationObject\n )\n );\n }\n}\n\nexport function zCreateTranslateLoader(\n http: HttpClient,\n path = './assets/i18n/',\n extension = '.json',\n includeZUI = true,\n zuiOverridePath?: string,\n customZUI?: Partial<Record<string, ZUITranslations>>\n): TranslateLoader {\n return new ZTranslateHttpLoader(http, path, extension, includeZUI, zuiOverridePath, customZUI);\n}\n\nfunction initializeTranslate(defaultLang: string): Promise<unknown> {\n const translate = inject(TranslateService);\n const savedLang = ZCacheService.get<string>(Z_LANG_CACHE_KEY) ?? defaultLang;\n translate.setFallbackLang(defaultLang);\n return firstValueFrom(translate.use(savedLang));\n}\n\nexport function provideZTranslate(config: ZTranslateProviderConfig = {}): EnvironmentProviders {\n const {\n defaultLang = 'vi',\n translationPath = './assets/i18n/',\n fileExtension = '.json',\n includeZUITranslations = true,\n zuiOverridePath,\n customZUITranslations,\n } = config;\n\n return makeEnvironmentProviders([\n provideTranslateService({\n fallbackLang: defaultLang,\n loader: {\n provide: TranslateLoader,\n useFactory: (http: HttpClient) =>\n zCreateTranslateLoader(\n http,\n translationPath,\n fileExtension,\n includeZUITranslations,\n zuiOverridePath,\n customZUITranslations\n ),\n deps: [HttpClient],\n },\n }),\n provideAppInitializer(() => initializeTranslate(defaultLang)),\n ]);\n}\n\nexport { Z_UI_TRANSLATIONS, mergeTranslations, getZUITranslations } from '@shival99/z-ui/i18n';\nexport type { ZUITranslations, ZUILanguage, ZUITranslationSet } from '@shival99/z-ui/i18n';\n","/**\n * Z-NgxMask Provider Types\n */\n\nexport interface ZNgxMaskConfig {\n /** Language code (vi, en, etc.) */\n lang?: string;\n /** Allow negative numbers */\n allowNegativeNumbers?: boolean;\n /** Enable validation */\n validation?: boolean;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -10,9 +10,8 @@ import { firstValueFrom, from, switchMap, of, catchError, throwError, tap, map,
|
|
|
10
10
|
import { TranslateService } from '@ngx-translate/core';
|
|
11
11
|
import { DOCUMENT, isPlatformBrowser } from '@angular/common';
|
|
12
12
|
|
|
13
|
-
const Z_CACHE_DEFAULT_PREFIX = 'z_';
|
|
14
13
|
class ZCacheService {
|
|
15
|
-
static _prefix =
|
|
14
|
+
static _prefix = 'z_';
|
|
16
15
|
static _encrypt = true;
|
|
17
16
|
static configure(config) {
|
|
18
17
|
if (config.prefix) {
|
|
@@ -38,8 +37,12 @@ class ZCacheService {
|
|
|
38
37
|
return null;
|
|
39
38
|
}
|
|
40
39
|
}
|
|
40
|
+
static _normalizeKey(key) {
|
|
41
|
+
return key.toLowerCase();
|
|
42
|
+
}
|
|
41
43
|
static _getFullKey(key, encrypt) {
|
|
42
|
-
const
|
|
44
|
+
const normalizedKey = ZCacheService._normalizeKey(key);
|
|
45
|
+
const prefixedKey = `${ZCacheService._prefix}${normalizedKey}`;
|
|
43
46
|
return encrypt ? ZCacheService._encode(prefixedKey) : prefixedKey;
|
|
44
47
|
}
|
|
45
48
|
static _safeOperation(operation, fallback) {
|
|
@@ -51,12 +54,6 @@ class ZCacheService {
|
|
|
51
54
|
return fallback;
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
|
-
/**
|
|
55
|
-
* Get a value from cache
|
|
56
|
-
* @param key - Cache key
|
|
57
|
-
* @param defaultValue - Default value if not found
|
|
58
|
-
* @param encrypt - Whether to use encryption (default: service config)
|
|
59
|
-
*/
|
|
60
57
|
static get(key, defaultValue, encrypt = ZCacheService._encrypt) {
|
|
61
58
|
return ZCacheService._safeOperation(() => {
|
|
62
59
|
const _key = ZCacheService._getFullKey(key, encrypt);
|
|
@@ -68,12 +65,6 @@ class ZCacheService {
|
|
|
68
65
|
return data ?? defaultValue;
|
|
69
66
|
}, defaultValue);
|
|
70
67
|
}
|
|
71
|
-
/**
|
|
72
|
-
* Set a value in cache
|
|
73
|
-
* @param key - Cache key
|
|
74
|
-
* @param data - Data to store
|
|
75
|
-
* @param encrypt - Whether to use encryption
|
|
76
|
-
*/
|
|
77
68
|
static set(key, data, encrypt = ZCacheService._encrypt) {
|
|
78
69
|
return ZCacheService._safeOperation(() => {
|
|
79
70
|
const _key = ZCacheService._getFullKey(key, encrypt);
|
|
@@ -82,35 +73,26 @@ class ZCacheService {
|
|
|
82
73
|
return true;
|
|
83
74
|
}, false);
|
|
84
75
|
}
|
|
85
|
-
|
|
86
|
-
* Delete a key from cache
|
|
87
|
-
* @param key - Cache key
|
|
88
|
-
* @param encrypt - Whether key is encrypted
|
|
89
|
-
*/
|
|
90
|
-
static delete(key, encrypt = ZCacheService._encrypt) {
|
|
76
|
+
static delete(key) {
|
|
91
77
|
return ZCacheService._safeOperation(() => {
|
|
92
|
-
const
|
|
93
|
-
|
|
78
|
+
const encryptedKey = ZCacheService._getFullKey(key, true);
|
|
79
|
+
const plainKey = ZCacheService._getFullKey(key, false);
|
|
80
|
+
localStorage.removeItem(encryptedKey);
|
|
81
|
+
localStorage.removeItem(plainKey);
|
|
94
82
|
return true;
|
|
95
83
|
}, false);
|
|
96
84
|
}
|
|
97
|
-
|
|
98
|
-
* Delete multiple keys from cache
|
|
99
|
-
* @param keys - Array of cache keys
|
|
100
|
-
* @param encrypt - Whether keys are encrypted
|
|
101
|
-
*/
|
|
102
|
-
static deleteMultiple(keys, encrypt = ZCacheService._encrypt) {
|
|
85
|
+
static deleteMultiple(keys) {
|
|
103
86
|
return ZCacheService._safeOperation(() => {
|
|
104
87
|
keys.forEach(key => {
|
|
105
|
-
const
|
|
106
|
-
|
|
88
|
+
const encryptedKey = ZCacheService._getFullKey(key, true);
|
|
89
|
+
const plainKey = ZCacheService._getFullKey(key, false);
|
|
90
|
+
localStorage.removeItem(encryptedKey);
|
|
91
|
+
localStorage.removeItem(plainKey);
|
|
107
92
|
});
|
|
108
93
|
return true;
|
|
109
94
|
}, false);
|
|
110
95
|
}
|
|
111
|
-
/**
|
|
112
|
-
* Clear all cache with the configured prefix
|
|
113
|
-
*/
|
|
114
96
|
static clear() {
|
|
115
97
|
return ZCacheService._safeOperation(() => {
|
|
116
98
|
const keysToRemove = [];
|
|
@@ -125,20 +107,12 @@ class ZCacheService {
|
|
|
125
107
|
return true;
|
|
126
108
|
}, false);
|
|
127
109
|
}
|
|
128
|
-
/**
|
|
129
|
-
* Check if a key exists in cache
|
|
130
|
-
* @param key - Cache key
|
|
131
|
-
* @param encrypt - Whether key is encrypted
|
|
132
|
-
*/
|
|
133
110
|
static has(key, encrypt = ZCacheService._encrypt) {
|
|
134
111
|
return ZCacheService._safeOperation(() => {
|
|
135
112
|
const _key = ZCacheService._getFullKey(key, encrypt);
|
|
136
113
|
return localStorage.getItem(_key) !== null;
|
|
137
114
|
}, false);
|
|
138
115
|
}
|
|
139
|
-
/**
|
|
140
|
-
* Get all keys with the configured prefix
|
|
141
|
-
*/
|
|
142
116
|
static keys() {
|
|
143
117
|
return ZCacheService._safeOperation(() => {
|
|
144
118
|
const result = [];
|
|
@@ -147,8 +121,9 @@ class ZCacheService {
|
|
|
147
121
|
const key = localStorage.key(i);
|
|
148
122
|
if (key?.startsWith(ZCacheService._prefix)) {
|
|
149
123
|
result.push(key.slice(ZCacheService._prefix.length));
|
|
124
|
+
continue;
|
|
150
125
|
}
|
|
151
|
-
|
|
126
|
+
if (key?.startsWith(prefixEncoded)) {
|
|
152
127
|
const decoded = ZCacheService._decode(key);
|
|
153
128
|
if (decoded) {
|
|
154
129
|
result.push(decoded.slice(ZCacheService._prefix.length));
|
|
@@ -935,25 +910,42 @@ class ZIndexDbService {
|
|
|
935
910
|
_stores = new Map();
|
|
936
911
|
_defaultStoreName;
|
|
937
912
|
_globalProtectedKeys;
|
|
913
|
+
_encrypt = true;
|
|
938
914
|
constructor(config = {}) {
|
|
939
915
|
this._dbName = config.dbName ?? Z_INDEXDB_DEFAULT_CONFIG.dbName;
|
|
940
916
|
this._version = config.version ?? Z_INDEXDB_DEFAULT_CONFIG.version;
|
|
941
917
|
this._mode = config.mode ?? Z_INDEXDB_DEFAULT_CONFIG.mode;
|
|
942
918
|
this._defaultStoreName = config.defaultStore ?? Z_INDEXDB_DEFAULT_CONFIG.defaultStore;
|
|
943
919
|
this._globalProtectedKeys = config.protectedKeys ?? [];
|
|
920
|
+
this._encrypt = config.encrypt ?? true;
|
|
944
921
|
if (config.stores?.length) {
|
|
945
922
|
config.stores.forEach(store => this._stores.set(store.name, store));
|
|
946
923
|
}
|
|
947
924
|
if (!this._stores.has(this._defaultStoreName)) {
|
|
948
|
-
this._stores.set(this._defaultStoreName, { name: this._defaultStoreName
|
|
925
|
+
this._stores.set(this._defaultStoreName, { name: this._defaultStoreName });
|
|
949
926
|
}
|
|
950
927
|
this._dbReady = this._initDb();
|
|
951
928
|
}
|
|
952
929
|
_getStoreConfig(storeName) {
|
|
953
930
|
const name = storeName ?? this._defaultStoreName;
|
|
954
|
-
return this._stores.get(name) ?? { name
|
|
931
|
+
return this._stores.get(name) ?? { name };
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* Determines if encryption should be used.
|
|
935
|
+
* Priority: per-call > store-level > global
|
|
936
|
+
* @param storeConfig - Store configuration
|
|
937
|
+
* @param perCallEncrypt - Per-call encrypt override (highest priority)
|
|
938
|
+
*/
|
|
939
|
+
_shouldEncrypt(storeConfig, perCallEncrypt) {
|
|
940
|
+
if (perCallEncrypt !== undefined) {
|
|
941
|
+
return perCallEncrypt;
|
|
942
|
+
}
|
|
943
|
+
return storeConfig.encrypt ?? this._encrypt;
|
|
955
944
|
}
|
|
956
|
-
|
|
945
|
+
_normalizeKey(key) {
|
|
946
|
+
return key.toLowerCase();
|
|
947
|
+
}
|
|
948
|
+
_encryptData(data) {
|
|
957
949
|
const payload = {
|
|
958
950
|
__z: true,
|
|
959
951
|
__t: typeof data,
|
|
@@ -961,7 +953,7 @@ class ZIndexDbService {
|
|
|
961
953
|
};
|
|
962
954
|
return btoa(encodeURIComponent(JSON.stringify(payload)));
|
|
963
955
|
}
|
|
964
|
-
|
|
956
|
+
_decryptData(data) {
|
|
965
957
|
try {
|
|
966
958
|
const decoded = JSON.parse(decodeURIComponent(atob(data)));
|
|
967
959
|
if (!decoded.__z) {
|
|
@@ -1009,7 +1001,7 @@ class ZIndexDbService {
|
|
|
1009
1001
|
await this._resetDatabase();
|
|
1010
1002
|
this._version = 1;
|
|
1011
1003
|
}
|
|
1012
|
-
|
|
1004
|
+
if (currentVersion > this._version && currentVersion < Z_INDEXDB_MAX_VERSION) {
|
|
1013
1005
|
this._version = currentVersion;
|
|
1014
1006
|
}
|
|
1015
1007
|
return new Promise((resolve, reject) => {
|
|
@@ -1102,8 +1094,10 @@ class ZIndexDbService {
|
|
|
1102
1094
|
}
|
|
1103
1095
|
return this._db.objectStoreNames.contains(storeName);
|
|
1104
1096
|
}
|
|
1105
|
-
async get(key,
|
|
1106
|
-
const storeConfig = this._getStoreConfig(storeName);
|
|
1097
|
+
async get(key, options) {
|
|
1098
|
+
const storeConfig = this._getStoreConfig(options?.storeName);
|
|
1099
|
+
const shouldEncrypt = this._shouldEncrypt(storeConfig, options?.encrypt);
|
|
1100
|
+
const defaultValue = options?.defaultValue;
|
|
1107
1101
|
return this._withRetry(async () => {
|
|
1108
1102
|
await this._dbReady;
|
|
1109
1103
|
if (!this._db) {
|
|
@@ -1118,7 +1112,8 @@ class ZIndexDbService {
|
|
|
1118
1112
|
return defaultValue;
|
|
1119
1113
|
}
|
|
1120
1114
|
}
|
|
1121
|
-
const
|
|
1115
|
+
const normalizedKey = this._normalizeKey(key);
|
|
1116
|
+
const _key = shouldEncrypt ? this._encryptData(normalizedKey) : normalizedKey;
|
|
1122
1117
|
return new Promise(resolve => {
|
|
1123
1118
|
try {
|
|
1124
1119
|
const transaction = this._db.transaction([storeConfig.name], this._mode);
|
|
@@ -1131,7 +1126,7 @@ class ZIndexDbService {
|
|
|
1131
1126
|
resolve(defaultValue);
|
|
1132
1127
|
return;
|
|
1133
1128
|
}
|
|
1134
|
-
const decrypted =
|
|
1129
|
+
const decrypted = shouldEncrypt ? this._decryptData(result) : result;
|
|
1135
1130
|
resolve(decrypted ?? defaultValue);
|
|
1136
1131
|
}
|
|
1137
1132
|
catch {
|
|
@@ -1147,8 +1142,9 @@ class ZIndexDbService {
|
|
|
1147
1142
|
});
|
|
1148
1143
|
});
|
|
1149
1144
|
}
|
|
1150
|
-
async set(key, value,
|
|
1151
|
-
const storeConfig = this._getStoreConfig(storeName);
|
|
1145
|
+
async set(key, value, options) {
|
|
1146
|
+
const storeConfig = this._getStoreConfig(options?.storeName);
|
|
1147
|
+
const shouldEncrypt = this._shouldEncrypt(storeConfig, options?.encrypt);
|
|
1152
1148
|
return this._withRetry(async () => {
|
|
1153
1149
|
await this._dbReady;
|
|
1154
1150
|
if (!this._db) {
|
|
@@ -1163,8 +1159,9 @@ class ZIndexDbService {
|
|
|
1163
1159
|
throw new Error(`Failed to create store "${storeConfig.name}"`);
|
|
1164
1160
|
}
|
|
1165
1161
|
}
|
|
1166
|
-
const
|
|
1167
|
-
const
|
|
1162
|
+
const normalizedKey = this._normalizeKey(key);
|
|
1163
|
+
const _key = shouldEncrypt ? this._encryptData(normalizedKey) : normalizedKey;
|
|
1164
|
+
const _value = shouldEncrypt ? this._encryptData(value) : value;
|
|
1168
1165
|
return new Promise((resolve, reject) => {
|
|
1169
1166
|
try {
|
|
1170
1167
|
const transaction = this._db.transaction([storeConfig.name], 'readwrite');
|
|
@@ -1180,7 +1177,18 @@ class ZIndexDbService {
|
|
|
1180
1177
|
});
|
|
1181
1178
|
});
|
|
1182
1179
|
}
|
|
1180
|
+
/**
|
|
1181
|
+
* Delete key(s) from IndexDB. If storeName not provided, deletes from all stores.
|
|
1182
|
+
* Tries both encrypted and non-encrypted versions of the key.
|
|
1183
|
+
*/
|
|
1183
1184
|
async delete(key, storeName) {
|
|
1185
|
+
if (storeName === undefined) {
|
|
1186
|
+
await Promise.all(this.getStoreNames().map(name => this._deleteFromStore(key, name)));
|
|
1187
|
+
return;
|
|
1188
|
+
}
|
|
1189
|
+
await this._deleteFromStore(key, storeName);
|
|
1190
|
+
}
|
|
1191
|
+
async _deleteFromStore(key, storeName) {
|
|
1184
1192
|
const storeConfig = this._getStoreConfig(storeName);
|
|
1185
1193
|
return this._withRetry(async () => {
|
|
1186
1194
|
await this._dbReady;
|
|
@@ -1199,8 +1207,9 @@ class ZIndexDbService {
|
|
|
1199
1207
|
const transaction = this._db.transaction([storeConfig.name], 'readwrite');
|
|
1200
1208
|
const store = transaction.objectStore(storeConfig.name);
|
|
1201
1209
|
keys.forEach(k => {
|
|
1202
|
-
const
|
|
1203
|
-
store.delete(
|
|
1210
|
+
const normalizedKey = this._normalizeKey(k);
|
|
1211
|
+
store.delete(normalizedKey);
|
|
1212
|
+
store.delete(this._encryptData(normalizedKey));
|
|
1204
1213
|
});
|
|
1205
1214
|
transaction.oncomplete = () => resolve();
|
|
1206
1215
|
transaction.onerror = () => reject(transaction.error);
|
|
@@ -1239,18 +1248,18 @@ class ZIndexDbService {
|
|
|
1239
1248
|
const transaction = this._db.transaction([storeConfig.name], 'readwrite');
|
|
1240
1249
|
const store = transaction.objectStore(storeConfig.name);
|
|
1241
1250
|
const keyRequest = store.getAllKeys();
|
|
1251
|
+
const protectedSet = new Set();
|
|
1252
|
+
protectedKeys.forEach(k => {
|
|
1253
|
+
const normalizedKey = this._normalizeKey(k);
|
|
1254
|
+
protectedSet.add(normalizedKey);
|
|
1255
|
+
protectedSet.add(this._encryptData(normalizedKey));
|
|
1256
|
+
});
|
|
1242
1257
|
keyRequest.onsuccess = () => {
|
|
1243
1258
|
const allKeys = keyRequest.result;
|
|
1244
|
-
const encryptedProtected = protectedKeys.map(k => this._encrypt(k));
|
|
1245
1259
|
allKeys.forEach(k => {
|
|
1246
|
-
if (!
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
if (!protectedKeys.includes(decrypted ?? '')) {
|
|
1250
|
-
store.delete(k);
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
catch {
|
|
1260
|
+
if (!protectedSet.has(k)) {
|
|
1261
|
+
const decrypted = this._decryptData(k);
|
|
1262
|
+
if (!decrypted || !protectedKeys.includes(decrypted)) {
|
|
1254
1263
|
store.delete(k);
|
|
1255
1264
|
}
|
|
1256
1265
|
}
|
|
@@ -1292,14 +1301,14 @@ class ZIndexDbService {
|
|
|
1292
1301
|
keys.forEach((key, index) => {
|
|
1293
1302
|
if (typeof key === 'string') {
|
|
1294
1303
|
try {
|
|
1295
|
-
const _key = storeConfig
|
|
1296
|
-
const _value = storeConfig
|
|
1304
|
+
const _key = this._shouldEncrypt(storeConfig) ? this._decryptData(key) : key;
|
|
1305
|
+
const _value = this._shouldEncrypt(storeConfig) ? this._decryptData(values[index]) : values[index];
|
|
1297
1306
|
if (_key && _value !== null) {
|
|
1298
1307
|
results[_key] = _value;
|
|
1299
1308
|
}
|
|
1300
1309
|
}
|
|
1301
1310
|
catch {
|
|
1302
|
-
|
|
1311
|
+
console.warn(`[ZIndexDb] Failed to decrypt entry for key: ${key}`);
|
|
1303
1312
|
}
|
|
1304
1313
|
}
|
|
1305
1314
|
});
|
|
@@ -1314,8 +1323,9 @@ class ZIndexDbService {
|
|
|
1314
1323
|
});
|
|
1315
1324
|
});
|
|
1316
1325
|
}
|
|
1317
|
-
async setMultiple(items,
|
|
1318
|
-
const storeConfig = this._getStoreConfig(storeName);
|
|
1326
|
+
async setMultiple(items, options) {
|
|
1327
|
+
const storeConfig = this._getStoreConfig(options?.storeName);
|
|
1328
|
+
const shouldEncrypt = this._shouldEncrypt(storeConfig, options?.encrypt);
|
|
1319
1329
|
const entries = Object.entries(items);
|
|
1320
1330
|
await this._dbReady;
|
|
1321
1331
|
if (this._db && !this._ensureStoreExists(storeConfig.name)) {
|
|
@@ -1338,8 +1348,9 @@ class ZIndexDbService {
|
|
|
1338
1348
|
const transaction = this._db.transaction([storeConfig.name], 'readwrite');
|
|
1339
1349
|
const store = transaction.objectStore(storeConfig.name);
|
|
1340
1350
|
batch.forEach(([key, value]) => {
|
|
1341
|
-
const
|
|
1342
|
-
const
|
|
1351
|
+
const normalizedKey = this._normalizeKey(key);
|
|
1352
|
+
const _key = shouldEncrypt ? this._encryptData(normalizedKey) : normalizedKey;
|
|
1353
|
+
const _value = shouldEncrypt ? this._encryptData(value) : value;
|
|
1343
1354
|
store.put(_value, _key);
|
|
1344
1355
|
});
|
|
1345
1356
|
transaction.oncomplete = () => resolve();
|
|
@@ -1361,6 +1372,10 @@ class ZIndexDbService {
|
|
|
1361
1372
|
this._stores.set(config.name, config);
|
|
1362
1373
|
await this._triggerUpgrade();
|
|
1363
1374
|
}
|
|
1375
|
+
async clearAll() {
|
|
1376
|
+
const storeNames = this.getStoreNames();
|
|
1377
|
+
await Promise.all(storeNames.map(storeName => this.clear(storeName)));
|
|
1378
|
+
}
|
|
1364
1379
|
}
|
|
1365
1380
|
|
|
1366
1381
|
const Z_LANG_TO_LOCALE = {
|
|
@@ -1688,11 +1703,11 @@ class ZHttpAbstractService {
|
|
|
1688
1703
|
}
|
|
1689
1704
|
async _cacheData(key, data, ttl) {
|
|
1690
1705
|
const cacheEntry = { data, timestamp: Date.now(), ttl };
|
|
1691
|
-
await this.indexDbService.set(key, cacheEntry, 'HttpCache');
|
|
1706
|
+
await this.indexDbService.set(key, cacheEntry, { storeName: 'HttpCache' });
|
|
1692
1707
|
}
|
|
1693
1708
|
async _getCachedData(key) {
|
|
1694
1709
|
try {
|
|
1695
|
-
const cached = await this.indexDbService.get(key,
|
|
1710
|
+
const cached = await this.indexDbService.get(key, { storeName: 'HttpCache' });
|
|
1696
1711
|
if (!cached) {
|
|
1697
1712
|
return null;
|
|
1698
1713
|
}
|
|
@@ -2027,7 +2042,7 @@ class ZThemeService {
|
|
|
2027
2042
|
if (this._hasConfigChanged()) {
|
|
2028
2043
|
return this._defaultTheme;
|
|
2029
2044
|
}
|
|
2030
|
-
return ZCacheService.get(Z_THEME_CACHE_KEY, undefined
|
|
2045
|
+
return ZCacheService.get(Z_THEME_CACHE_KEY, undefined) ?? this._defaultTheme;
|
|
2031
2046
|
}
|
|
2032
2047
|
_getInitialDarkMode() {
|
|
2033
2048
|
if (!this._isBrowser) {
|
|
@@ -2039,7 +2054,7 @@ class ZThemeService {
|
|
|
2039
2054
|
return ZCacheService.get(Z_DARK_MODE_CACHE_KEY, undefined, true) ?? this._defaultDarkMode;
|
|
2040
2055
|
}
|
|
2041
2056
|
_hasConfigChanged() {
|
|
2042
|
-
const cachedConfig = ZCacheService.get(Z_THEME_CONFIG_CACHE_KEY, undefined
|
|
2057
|
+
const cachedConfig = ZCacheService.get(Z_THEME_CONFIG_CACHE_KEY, undefined);
|
|
2043
2058
|
if (!cachedConfig) {
|
|
2044
2059
|
return true;
|
|
2045
2060
|
}
|
|
@@ -2055,7 +2070,7 @@ class ZThemeService {
|
|
|
2055
2070
|
defaultTheme: this._defaultTheme,
|
|
2056
2071
|
defaultDarkMode: this._defaultDarkMode,
|
|
2057
2072
|
};
|
|
2058
|
-
ZCacheService.set(Z_THEME_CONFIG_CACHE_KEY, currentConfig
|
|
2073
|
+
ZCacheService.set(Z_THEME_CONFIG_CACHE_KEY, currentConfig);
|
|
2059
2074
|
}
|
|
2060
2075
|
_loadThemeCSS(theme, onLoad) {
|
|
2061
2076
|
const cssPath = Z_THEME_CSS_MAP[theme];
|