@shival99/z-ui 1.4.6 → 1.4.8
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 +85 -86
- package/fesm2022/shival99-z-ui-services.mjs.map +1 -1
- package/package.json +1 -1
- package/types/shival99-z-ui-providers.d.ts +23 -2
- package/types/shival99-z-ui-services.d.ts +32 -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) {
|
|
@@ -51,12 +50,6 @@ class ZCacheService {
|
|
|
51
50
|
return fallback;
|
|
52
51
|
}
|
|
53
52
|
}
|
|
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
53
|
static get(key, defaultValue, encrypt = ZCacheService._encrypt) {
|
|
61
54
|
return ZCacheService._safeOperation(() => {
|
|
62
55
|
const _key = ZCacheService._getFullKey(key, encrypt);
|
|
@@ -68,12 +61,6 @@ class ZCacheService {
|
|
|
68
61
|
return data ?? defaultValue;
|
|
69
62
|
}, defaultValue);
|
|
70
63
|
}
|
|
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
64
|
static set(key, data, encrypt = ZCacheService._encrypt) {
|
|
78
65
|
return ZCacheService._safeOperation(() => {
|
|
79
66
|
const _key = ZCacheService._getFullKey(key, encrypt);
|
|
@@ -82,35 +69,26 @@ class ZCacheService {
|
|
|
82
69
|
return true;
|
|
83
70
|
}, false);
|
|
84
71
|
}
|
|
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) {
|
|
72
|
+
static delete(key) {
|
|
91
73
|
return ZCacheService._safeOperation(() => {
|
|
92
|
-
const
|
|
93
|
-
|
|
74
|
+
const encryptedKey = ZCacheService._getFullKey(key, true);
|
|
75
|
+
const plainKey = ZCacheService._getFullKey(key, false);
|
|
76
|
+
localStorage.removeItem(encryptedKey);
|
|
77
|
+
localStorage.removeItem(plainKey);
|
|
94
78
|
return true;
|
|
95
79
|
}, false);
|
|
96
80
|
}
|
|
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) {
|
|
81
|
+
static deleteMultiple(keys) {
|
|
103
82
|
return ZCacheService._safeOperation(() => {
|
|
104
83
|
keys.forEach(key => {
|
|
105
|
-
const
|
|
106
|
-
|
|
84
|
+
const encryptedKey = ZCacheService._getFullKey(key, true);
|
|
85
|
+
const plainKey = ZCacheService._getFullKey(key, false);
|
|
86
|
+
localStorage.removeItem(encryptedKey);
|
|
87
|
+
localStorage.removeItem(plainKey);
|
|
107
88
|
});
|
|
108
89
|
return true;
|
|
109
90
|
}, false);
|
|
110
91
|
}
|
|
111
|
-
/**
|
|
112
|
-
* Clear all cache with the configured prefix
|
|
113
|
-
*/
|
|
114
92
|
static clear() {
|
|
115
93
|
return ZCacheService._safeOperation(() => {
|
|
116
94
|
const keysToRemove = [];
|
|
@@ -125,20 +103,12 @@ class ZCacheService {
|
|
|
125
103
|
return true;
|
|
126
104
|
}, false);
|
|
127
105
|
}
|
|
128
|
-
/**
|
|
129
|
-
* Check if a key exists in cache
|
|
130
|
-
* @param key - Cache key
|
|
131
|
-
* @param encrypt - Whether key is encrypted
|
|
132
|
-
*/
|
|
133
106
|
static has(key, encrypt = ZCacheService._encrypt) {
|
|
134
107
|
return ZCacheService._safeOperation(() => {
|
|
135
108
|
const _key = ZCacheService._getFullKey(key, encrypt);
|
|
136
109
|
return localStorage.getItem(_key) !== null;
|
|
137
110
|
}, false);
|
|
138
111
|
}
|
|
139
|
-
/**
|
|
140
|
-
* Get all keys with the configured prefix
|
|
141
|
-
*/
|
|
142
112
|
static keys() {
|
|
143
113
|
return ZCacheService._safeOperation(() => {
|
|
144
114
|
const result = [];
|
|
@@ -147,8 +117,9 @@ class ZCacheService {
|
|
|
147
117
|
const key = localStorage.key(i);
|
|
148
118
|
if (key?.startsWith(ZCacheService._prefix)) {
|
|
149
119
|
result.push(key.slice(ZCacheService._prefix.length));
|
|
120
|
+
continue;
|
|
150
121
|
}
|
|
151
|
-
|
|
122
|
+
if (key?.startsWith(prefixEncoded)) {
|
|
152
123
|
const decoded = ZCacheService._decode(key);
|
|
153
124
|
if (decoded) {
|
|
154
125
|
result.push(decoded.slice(ZCacheService._prefix.length));
|
|
@@ -935,25 +906,39 @@ class ZIndexDbService {
|
|
|
935
906
|
_stores = new Map();
|
|
936
907
|
_defaultStoreName;
|
|
937
908
|
_globalProtectedKeys;
|
|
909
|
+
_encrypt = true;
|
|
938
910
|
constructor(config = {}) {
|
|
939
911
|
this._dbName = config.dbName ?? Z_INDEXDB_DEFAULT_CONFIG.dbName;
|
|
940
912
|
this._version = config.version ?? Z_INDEXDB_DEFAULT_CONFIG.version;
|
|
941
913
|
this._mode = config.mode ?? Z_INDEXDB_DEFAULT_CONFIG.mode;
|
|
942
914
|
this._defaultStoreName = config.defaultStore ?? Z_INDEXDB_DEFAULT_CONFIG.defaultStore;
|
|
943
915
|
this._globalProtectedKeys = config.protectedKeys ?? [];
|
|
916
|
+
this._encrypt = config.encrypt ?? true;
|
|
944
917
|
if (config.stores?.length) {
|
|
945
918
|
config.stores.forEach(store => this._stores.set(store.name, store));
|
|
946
919
|
}
|
|
947
920
|
if (!this._stores.has(this._defaultStoreName)) {
|
|
948
|
-
this._stores.set(this._defaultStoreName, { name: this._defaultStoreName
|
|
921
|
+
this._stores.set(this._defaultStoreName, { name: this._defaultStoreName });
|
|
949
922
|
}
|
|
950
923
|
this._dbReady = this._initDb();
|
|
951
924
|
}
|
|
952
925
|
_getStoreConfig(storeName) {
|
|
953
926
|
const name = storeName ?? this._defaultStoreName;
|
|
954
|
-
return this._stores.get(name) ?? { name
|
|
927
|
+
return this._stores.get(name) ?? { name };
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* Determines if encryption should be used.
|
|
931
|
+
* Priority: per-call > store-level > global
|
|
932
|
+
* @param storeConfig - Store configuration
|
|
933
|
+
* @param perCallEncrypt - Per-call encrypt override (highest priority)
|
|
934
|
+
*/
|
|
935
|
+
_shouldEncrypt(storeConfig, perCallEncrypt) {
|
|
936
|
+
if (perCallEncrypt !== undefined) {
|
|
937
|
+
return perCallEncrypt;
|
|
938
|
+
}
|
|
939
|
+
return storeConfig.encrypt ?? this._encrypt;
|
|
955
940
|
}
|
|
956
|
-
|
|
941
|
+
_encryptData(data) {
|
|
957
942
|
const payload = {
|
|
958
943
|
__z: true,
|
|
959
944
|
__t: typeof data,
|
|
@@ -961,7 +946,7 @@ class ZIndexDbService {
|
|
|
961
946
|
};
|
|
962
947
|
return btoa(encodeURIComponent(JSON.stringify(payload)));
|
|
963
948
|
}
|
|
964
|
-
|
|
949
|
+
_decryptData(data) {
|
|
965
950
|
try {
|
|
966
951
|
const decoded = JSON.parse(decodeURIComponent(atob(data)));
|
|
967
952
|
if (!decoded.__z) {
|
|
@@ -1009,7 +994,7 @@ class ZIndexDbService {
|
|
|
1009
994
|
await this._resetDatabase();
|
|
1010
995
|
this._version = 1;
|
|
1011
996
|
}
|
|
1012
|
-
|
|
997
|
+
if (currentVersion > this._version && currentVersion < Z_INDEXDB_MAX_VERSION) {
|
|
1013
998
|
this._version = currentVersion;
|
|
1014
999
|
}
|
|
1015
1000
|
return new Promise((resolve, reject) => {
|
|
@@ -1102,8 +1087,10 @@ class ZIndexDbService {
|
|
|
1102
1087
|
}
|
|
1103
1088
|
return this._db.objectStoreNames.contains(storeName);
|
|
1104
1089
|
}
|
|
1105
|
-
async get(key,
|
|
1106
|
-
const storeConfig = this._getStoreConfig(storeName);
|
|
1090
|
+
async get(key, options) {
|
|
1091
|
+
const storeConfig = this._getStoreConfig(options?.storeName);
|
|
1092
|
+
const shouldEncrypt = this._shouldEncrypt(storeConfig, options?.encrypt);
|
|
1093
|
+
const defaultValue = options?.defaultValue;
|
|
1107
1094
|
return this._withRetry(async () => {
|
|
1108
1095
|
await this._dbReady;
|
|
1109
1096
|
if (!this._db) {
|
|
@@ -1118,7 +1105,7 @@ class ZIndexDbService {
|
|
|
1118
1105
|
return defaultValue;
|
|
1119
1106
|
}
|
|
1120
1107
|
}
|
|
1121
|
-
const _key =
|
|
1108
|
+
const _key = shouldEncrypt ? this._encryptData(key) : key;
|
|
1122
1109
|
return new Promise(resolve => {
|
|
1123
1110
|
try {
|
|
1124
1111
|
const transaction = this._db.transaction([storeConfig.name], this._mode);
|
|
@@ -1131,7 +1118,7 @@ class ZIndexDbService {
|
|
|
1131
1118
|
resolve(defaultValue);
|
|
1132
1119
|
return;
|
|
1133
1120
|
}
|
|
1134
|
-
const decrypted =
|
|
1121
|
+
const decrypted = shouldEncrypt ? this._decryptData(result) : result;
|
|
1135
1122
|
resolve(decrypted ?? defaultValue);
|
|
1136
1123
|
}
|
|
1137
1124
|
catch {
|
|
@@ -1147,8 +1134,9 @@ class ZIndexDbService {
|
|
|
1147
1134
|
});
|
|
1148
1135
|
});
|
|
1149
1136
|
}
|
|
1150
|
-
async set(key, value,
|
|
1151
|
-
const storeConfig = this._getStoreConfig(storeName);
|
|
1137
|
+
async set(key, value, options) {
|
|
1138
|
+
const storeConfig = this._getStoreConfig(options?.storeName);
|
|
1139
|
+
const shouldEncrypt = this._shouldEncrypt(storeConfig, options?.encrypt);
|
|
1152
1140
|
return this._withRetry(async () => {
|
|
1153
1141
|
await this._dbReady;
|
|
1154
1142
|
if (!this._db) {
|
|
@@ -1163,8 +1151,8 @@ class ZIndexDbService {
|
|
|
1163
1151
|
throw new Error(`Failed to create store "${storeConfig.name}"`);
|
|
1164
1152
|
}
|
|
1165
1153
|
}
|
|
1166
|
-
const _key =
|
|
1167
|
-
const _value =
|
|
1154
|
+
const _key = shouldEncrypt ? this._encryptData(key) : key;
|
|
1155
|
+
const _value = shouldEncrypt ? this._encryptData(value) : value;
|
|
1168
1156
|
return new Promise((resolve, reject) => {
|
|
1169
1157
|
try {
|
|
1170
1158
|
const transaction = this._db.transaction([storeConfig.name], 'readwrite');
|
|
@@ -1180,7 +1168,18 @@ class ZIndexDbService {
|
|
|
1180
1168
|
});
|
|
1181
1169
|
});
|
|
1182
1170
|
}
|
|
1171
|
+
/**
|
|
1172
|
+
* Delete key(s) from IndexDB. If storeName not provided, deletes from all stores.
|
|
1173
|
+
* Tries both encrypted and non-encrypted versions of the key.
|
|
1174
|
+
*/
|
|
1183
1175
|
async delete(key, storeName) {
|
|
1176
|
+
if (storeName === undefined) {
|
|
1177
|
+
await Promise.all(this.getStoreNames().map(name => this._deleteFromStore(key, name)));
|
|
1178
|
+
return;
|
|
1179
|
+
}
|
|
1180
|
+
await this._deleteFromStore(key, storeName);
|
|
1181
|
+
}
|
|
1182
|
+
async _deleteFromStore(key, storeName) {
|
|
1184
1183
|
const storeConfig = this._getStoreConfig(storeName);
|
|
1185
1184
|
return this._withRetry(async () => {
|
|
1186
1185
|
await this._dbReady;
|
|
@@ -1199,8 +1198,8 @@ class ZIndexDbService {
|
|
|
1199
1198
|
const transaction = this._db.transaction([storeConfig.name], 'readwrite');
|
|
1200
1199
|
const store = transaction.objectStore(storeConfig.name);
|
|
1201
1200
|
keys.forEach(k => {
|
|
1202
|
-
|
|
1203
|
-
store.delete(
|
|
1201
|
+
store.delete(k);
|
|
1202
|
+
store.delete(this._encryptData(k));
|
|
1204
1203
|
});
|
|
1205
1204
|
transaction.oncomplete = () => resolve();
|
|
1206
1205
|
transaction.onerror = () => reject(transaction.error);
|
|
@@ -1239,18 +1238,17 @@ class ZIndexDbService {
|
|
|
1239
1238
|
const transaction = this._db.transaction([storeConfig.name], 'readwrite');
|
|
1240
1239
|
const store = transaction.objectStore(storeConfig.name);
|
|
1241
1240
|
const keyRequest = store.getAllKeys();
|
|
1241
|
+
const protectedSet = new Set();
|
|
1242
|
+
protectedKeys.forEach(k => {
|
|
1243
|
+
protectedSet.add(k);
|
|
1244
|
+
protectedSet.add(this._encryptData(k));
|
|
1245
|
+
});
|
|
1242
1246
|
keyRequest.onsuccess = () => {
|
|
1243
1247
|
const allKeys = keyRequest.result;
|
|
1244
|
-
const encryptedProtected = protectedKeys.map(k => this._encrypt(k));
|
|
1245
1248
|
allKeys.forEach(k => {
|
|
1246
|
-
if (!
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
if (!protectedKeys.includes(decrypted ?? '')) {
|
|
1250
|
-
store.delete(k);
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
catch {
|
|
1249
|
+
if (!protectedSet.has(k)) {
|
|
1250
|
+
const decrypted = this._decryptData(k);
|
|
1251
|
+
if (!decrypted || !protectedKeys.includes(decrypted)) {
|
|
1254
1252
|
store.delete(k);
|
|
1255
1253
|
}
|
|
1256
1254
|
}
|
|
@@ -1292,14 +1290,14 @@ class ZIndexDbService {
|
|
|
1292
1290
|
keys.forEach((key, index) => {
|
|
1293
1291
|
if (typeof key === 'string') {
|
|
1294
1292
|
try {
|
|
1295
|
-
const _key = storeConfig
|
|
1296
|
-
const _value = storeConfig
|
|
1293
|
+
const _key = this._shouldEncrypt(storeConfig) ? this._decryptData(key) : key;
|
|
1294
|
+
const _value = this._shouldEncrypt(storeConfig) ? this._decryptData(values[index]) : values[index];
|
|
1297
1295
|
if (_key && _value !== null) {
|
|
1298
1296
|
results[_key] = _value;
|
|
1299
1297
|
}
|
|
1300
1298
|
}
|
|
1301
1299
|
catch {
|
|
1302
|
-
|
|
1300
|
+
console.warn(`[ZIndexDb] Failed to decrypt entry for key: ${key}`);
|
|
1303
1301
|
}
|
|
1304
1302
|
}
|
|
1305
1303
|
});
|
|
@@ -1314,8 +1312,9 @@ class ZIndexDbService {
|
|
|
1314
1312
|
});
|
|
1315
1313
|
});
|
|
1316
1314
|
}
|
|
1317
|
-
async setMultiple(items,
|
|
1318
|
-
const storeConfig = this._getStoreConfig(storeName);
|
|
1315
|
+
async setMultiple(items, options) {
|
|
1316
|
+
const storeConfig = this._getStoreConfig(options?.storeName);
|
|
1317
|
+
const shouldEncrypt = this._shouldEncrypt(storeConfig, options?.encrypt);
|
|
1319
1318
|
const entries = Object.entries(items);
|
|
1320
1319
|
await this._dbReady;
|
|
1321
1320
|
if (this._db && !this._ensureStoreExists(storeConfig.name)) {
|
|
@@ -1338,8 +1337,8 @@ class ZIndexDbService {
|
|
|
1338
1337
|
const transaction = this._db.transaction([storeConfig.name], 'readwrite');
|
|
1339
1338
|
const store = transaction.objectStore(storeConfig.name);
|
|
1340
1339
|
batch.forEach(([key, value]) => {
|
|
1341
|
-
const _key =
|
|
1342
|
-
const _value =
|
|
1340
|
+
const _key = shouldEncrypt ? this._encryptData(key) : key;
|
|
1341
|
+
const _value = shouldEncrypt ? this._encryptData(value) : value;
|
|
1343
1342
|
store.put(_value, _key);
|
|
1344
1343
|
});
|
|
1345
1344
|
transaction.oncomplete = () => resolve();
|
|
@@ -1361,6 +1360,10 @@ class ZIndexDbService {
|
|
|
1361
1360
|
this._stores.set(config.name, config);
|
|
1362
1361
|
await this._triggerUpgrade();
|
|
1363
1362
|
}
|
|
1363
|
+
async clearAll() {
|
|
1364
|
+
const storeNames = this.getStoreNames();
|
|
1365
|
+
await Promise.all(storeNames.map(storeName => this.clear(storeName)));
|
|
1366
|
+
}
|
|
1364
1367
|
}
|
|
1365
1368
|
|
|
1366
1369
|
const Z_LANG_TO_LOCALE = {
|
|
@@ -1480,7 +1483,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
|
|
|
1480
1483
|
|
|
1481
1484
|
const Z_HTTP_DEFAULT_CONFIG = {
|
|
1482
1485
|
defaultCacheTime: 3 * 60 * 1000,
|
|
1483
|
-
networkCheckCacheTime:
|
|
1486
|
+
networkCheckCacheTime: 5000,
|
|
1484
1487
|
tokenKey: 'Z_TOKEN',
|
|
1485
1488
|
userInfoKey: 'Z_USER_INFO',
|
|
1486
1489
|
lastUrlKey: 'Z_LAST_URL',
|
|
@@ -1688,11 +1691,11 @@ class ZHttpAbstractService {
|
|
|
1688
1691
|
}
|
|
1689
1692
|
async _cacheData(key, data, ttl) {
|
|
1690
1693
|
const cacheEntry = { data, timestamp: Date.now(), ttl };
|
|
1691
|
-
await this.indexDbService.set(key, cacheEntry, 'HttpCache');
|
|
1694
|
+
await this.indexDbService.set(key, cacheEntry, { storeName: 'HttpCache' });
|
|
1692
1695
|
}
|
|
1693
1696
|
async _getCachedData(key) {
|
|
1694
1697
|
try {
|
|
1695
|
-
const cached = await this.indexDbService.get(key,
|
|
1698
|
+
const cached = await this.indexDbService.get(key, { storeName: 'HttpCache' });
|
|
1696
1699
|
if (!cached) {
|
|
1697
1700
|
return null;
|
|
1698
1701
|
}
|
|
@@ -1750,7 +1753,7 @@ class ZHttpAbstractService {
|
|
|
1750
1753
|
status: statusCode,
|
|
1751
1754
|
error: localizedError,
|
|
1752
1755
|
});
|
|
1753
|
-
this._handleStatusCode(statusCode);
|
|
1756
|
+
void this._handleStatusCode(statusCode);
|
|
1754
1757
|
return throwError(() => localizedError);
|
|
1755
1758
|
}
|
|
1756
1759
|
_buildErrorObject(error, statusCode, endpoint, method, body, options) {
|
|
@@ -1811,18 +1814,13 @@ class ZHttpAbstractService {
|
|
|
1811
1814
|
}
|
|
1812
1815
|
return this.translateService.instant('i18n_z_ui_http_error_401_permission');
|
|
1813
1816
|
}
|
|
1814
|
-
_handleStatusCode(statusCode) {
|
|
1817
|
+
async _handleStatusCode(statusCode) {
|
|
1815
1818
|
if (statusCode !== 401) {
|
|
1816
1819
|
return;
|
|
1817
1820
|
}
|
|
1818
|
-
|
|
1819
|
-
if (!token) {
|
|
1820
|
-
this._redirectToLogin();
|
|
1821
|
-
return;
|
|
1822
|
-
}
|
|
1823
|
-
this.router.navigate([this.config.homeRoute]).catch(console.error);
|
|
1821
|
+
await this._redirectToLogin();
|
|
1824
1822
|
}
|
|
1825
|
-
_redirectToLogin() {
|
|
1823
|
+
async _redirectToLogin() {
|
|
1826
1824
|
const currentUrl = this.router.url;
|
|
1827
1825
|
const shouldSaveUrl = currentUrl &&
|
|
1828
1826
|
currentUrl !== '/' &&
|
|
@@ -1830,9 +1828,10 @@ class ZHttpAbstractService {
|
|
|
1830
1828
|
!currentUrl.includes(this.config.unauthorizedRoute);
|
|
1831
1829
|
if (shouldSaveUrl) {
|
|
1832
1830
|
this.cacheService.set(this.config.lastUrlKey, currentUrl);
|
|
1831
|
+
await this.indexDbService.set(this.config.lastUrlKey, currentUrl).catch(console.error);
|
|
1833
1832
|
}
|
|
1834
|
-
this.indexDbService.clear('HttpCache').catch(console.error);
|
|
1835
1833
|
this.cacheService.deleteMultiple([this.config.tokenKey, this.config.userInfoKey]);
|
|
1834
|
+
await this.indexDbService.clear('HttpCache').catch(console.error);
|
|
1836
1835
|
this.router.navigate([this.config.loginRoute]).catch(console.error);
|
|
1837
1836
|
}
|
|
1838
1837
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZHttpAbstractService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|