@umituz/react-native-design-system 4.27.13 → 4.27.15

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 (28) hide show
  1. package/package.json +1 -4
  2. package/src/core/cache/domain/CleanupStrategy.ts +115 -0
  3. package/src/core/cache/domain/UnifiedCache.ts +196 -0
  4. package/src/core/cache/domain/types.ts +18 -0
  5. package/src/core/cache/index.ts +16 -0
  6. package/src/core/cache/infrastructure/CacheFactory.ts +102 -0
  7. package/src/core/index.ts +21 -0
  8. package/src/core/permissions/domain/PermissionHandler.ts +139 -0
  9. package/src/core/permissions/domain/types.ts +49 -0
  10. package/src/core/permissions/index.ts +15 -0
  11. package/src/core/repositories/domain/RepositoryKeyFactory.ts +41 -0
  12. package/src/core/repositories/domain/RepositoryUtils.ts +86 -0
  13. package/src/core/repositories/domain/types.ts +59 -0
  14. package/src/core/repositories/index.ts +23 -0
  15. package/src/device/detection/deviceDetection.ts +8 -2
  16. package/src/haptics/infrastructure/services/HapticService.ts +4 -1
  17. package/src/index.ts +1 -0
  18. package/src/media/domain/strategies/CameraPickerStrategy.ts +65 -0
  19. package/src/media/domain/strategies/LibraryPickerStrategy.ts +54 -0
  20. package/src/media/domain/strategies/PickerStrategy.ts +61 -0
  21. package/src/media/domain/strategies/index.ts +13 -0
  22. package/src/media/infrastructure/services/MediaPickerService.ts +118 -108
  23. package/src/media/infrastructure/utils/PermissionManager.ts +68 -66
  24. package/src/media/presentation/hooks/useMedia.ts +16 -4
  25. package/src/storage/cache/infrastructure/TTLCache.ts +3 -0
  26. package/src/tanstack/domain/repositories/BaseRepository.ts +18 -1
  27. package/src/timezone/infrastructure/utils/SimpleCache.ts +30 -75
  28. package/src/uuid/infrastructure/utils/UUIDUtils.ts +4 -1
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Repository Key Factory
3
+ *
4
+ * Generic query key factory for repositories.
5
+ * Provides consistent query key structure across all repositories.
6
+ */
7
+
8
+ import type { QueryKeyFactory, ListParams } from './types';
9
+
10
+ /**
11
+ * Create query key factory for a resource
12
+ *
13
+ * @param resource - Resource name (e.g., 'users', 'posts')
14
+ * @returns Query key factory
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const keys = createRepositoryKeyFactory('users');
19
+ *
20
+ * keys.all(); // ['users']
21
+ * keys.lists(); // ['users', 'list']
22
+ * keys.list({ page: 1 }); // ['users', 'list', { page: 1 }]
23
+ * keys.details(); // ['users', 'detail']
24
+ * keys.detail(123); // ['users', 'detail', 123]
25
+ * ```
26
+ */
27
+ export function createRepositoryKeyFactory(
28
+ resource: string
29
+ ): QueryKeyFactory {
30
+ return {
31
+ all: () => [resource] as const,
32
+
33
+ lists: () => [resource, 'list'] as const,
34
+
35
+ list: (params: ListParams) => [resource, 'list', params] as const,
36
+
37
+ details: () => [resource, 'detail'] as const,
38
+
39
+ detail: (id: string | number) => [resource, 'detail', id] as const,
40
+ };
41
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Repository Utilities
3
+ *
4
+ * Common utilities for repository implementations.
5
+ * Provides caching options and helper functions.
6
+ */
7
+
8
+ import type { RepositoryOptions, ListParams } from './types';
9
+
10
+ /**
11
+ * Default cache options
12
+ */
13
+ const DEFAULT_CACHE_OPTIONS = {
14
+ staleTime: 5 * 60 * 1000, // 5 minutes
15
+ gcTime: 10 * 60 * 1000, // 10 minutes (formerly cacheTime)
16
+ };
17
+
18
+ /**
19
+ * Merge repository options with defaults
20
+ *
21
+ * @param options - User provided options
22
+ * @returns Merged options
23
+ */
24
+ export function mergeRepositoryOptions(
25
+ options: RepositoryOptions = {}
26
+ ): Required<RepositoryOptions> {
27
+ return {
28
+ cache: {
29
+ staleTime: options.cache?.staleTime ?? DEFAULT_CACHE_OPTIONS.staleTime,
30
+ gcTime: options.cache?.gcTime ?? DEFAULT_CACHE_OPTIONS.gcTime,
31
+ },
32
+ debug: options.debug ?? __DEV__,
33
+ };
34
+ }
35
+
36
+ /**
37
+ * Get cache options from repository options
38
+ *
39
+ * @param options - Repository options
40
+ * @returns Cache options with defaults
41
+ */
42
+ export function getCacheOptions(options: RepositoryOptions): {
43
+ staleTime: number;
44
+ gcTime: number;
45
+ } {
46
+ const merged = mergeRepositoryOptions(options);
47
+ return {
48
+ staleTime: merged.cache.staleTime,
49
+ gcTime: merged.cache.gcTime,
50
+ };
51
+ }
52
+
53
+ /**
54
+ * Normalize list parameters
55
+ *
56
+ * @param params - List parameters
57
+ * @returns Normalized parameters
58
+ */
59
+ export function normalizeListParams(params: ListParams = {}): ListParams {
60
+ return {
61
+ page: params.page ?? 1,
62
+ limit: params.limit ?? 20,
63
+ sort: params.sort ?? 'createdAt',
64
+ filter: params.filter ?? {},
65
+ };
66
+ }
67
+
68
+ /**
69
+ * Create debug logger for repository
70
+ *
71
+ * @param resource - Resource name
72
+ * @param enabled - Enable logging
73
+ * @returns Logger function
74
+ */
75
+ export function createRepositoryLogger(
76
+ resource: string,
77
+ enabled: boolean = __DEV__
78
+ ): (method: string, ...args: unknown[]) => void {
79
+ if (!enabled) {
80
+ return () => {};
81
+ }
82
+
83
+ return (method: string, ...args: unknown[]) => {
84
+ console.log(`[Repository:${resource}] ${method}`, ...args);
85
+ };
86
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Core Repository Domain Types
3
+ *
4
+ * Shared types for repository implementations
5
+ */
6
+
7
+ /**
8
+ * Repository options
9
+ */
10
+ export interface RepositoryOptions {
11
+ /**
12
+ * Cache configuration
13
+ */
14
+ cache?: {
15
+ staleTime?: number;
16
+ gcTime?: number;
17
+ };
18
+
19
+ /**
20
+ * Enable debug logging
21
+ */
22
+ debug?: boolean;
23
+ }
24
+
25
+ /**
26
+ * List parameters for fetch operations
27
+ */
28
+ export interface ListParams {
29
+ page?: number;
30
+ limit?: number;
31
+ sort?: string;
32
+ filter?: Record<string, unknown>;
33
+ }
34
+
35
+ /**
36
+ * Create parameters
37
+ */
38
+ export interface CreateParams<TVariables> {
39
+ data: TVariables;
40
+ }
41
+
42
+ /**
43
+ * Update parameters
44
+ */
45
+ export interface UpdateParams<TVariables> {
46
+ id: string | number;
47
+ data: TVariables;
48
+ }
49
+
50
+ /**
51
+ * Query key factory result
52
+ */
53
+ export type QueryKeyFactory = {
54
+ all: () => readonly string[];
55
+ lists: () => readonly string[];
56
+ list: (params: ListParams) => readonly string[];
57
+ details: () => readonly string[];
58
+ detail: (id: string | number) => readonly string[];
59
+ };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Core Repositories Module
3
+ *
4
+ * Common utilities and types for repository implementations.
5
+ * TanStack and Storage repositories remain separate but share these utilities.
6
+ */
7
+
8
+ export { createRepositoryKeyFactory } from './domain/RepositoryKeyFactory';
9
+ export type { QueryKeyFactory } from './domain/types';
10
+
11
+ export {
12
+ mergeRepositoryOptions,
13
+ getCacheOptions,
14
+ normalizeListParams,
15
+ createRepositoryLogger,
16
+ } from './domain/RepositoryUtils';
17
+
18
+ export type {
19
+ RepositoryOptions,
20
+ ListParams,
21
+ CreateParams,
22
+ UpdateParams,
23
+ } from './domain/types';
@@ -18,7 +18,10 @@ const getDeviceModule = (): typeof import('expo-device') | null => {
18
18
  // eslint-disable-next-line @typescript-eslint/no-require-imports
19
19
  _deviceModule = require('expo-device') as typeof import('expo-device');
20
20
  return _deviceModule;
21
- } catch {
21
+ } catch (error) {
22
+ if (__DEV__) {
23
+ console.warn('[deviceDetection] expo-device not available:', error);
24
+ }
22
25
  return null;
23
26
  }
24
27
  };
@@ -35,7 +38,10 @@ export const getScreenDimensions = () => {
35
38
  try {
36
39
  validateScreenDimensions(width, height);
37
40
  return { width, height };
38
- } catch {
41
+ } catch (error) {
42
+ if (__DEV__) {
43
+ console.warn('[deviceDetection] Invalid screen dimensions, using fallback:', error);
44
+ }
39
45
  return { width: 414, height: 896 };
40
46
  }
41
47
  };
@@ -31,7 +31,10 @@ const getHapticsModule = (): typeof import('expo-haptics') | null => {
31
31
  // eslint-disable-next-line @typescript-eslint/no-require-imports
32
32
  _hapticsModule = require('expo-haptics') as typeof import('expo-haptics');
33
33
  return _hapticsModule;
34
- } catch {
34
+ } catch (error) {
35
+ if (__DEV__) {
36
+ console.warn('[HapticService] expo-haptics not available:', error);
37
+ }
35
38
  return null;
36
39
  }
37
40
  };
package/src/index.ts CHANGED
@@ -36,6 +36,7 @@
36
36
  * /carousel - Carousel components
37
37
  * /init - createAppInitializer, createEnvConfig
38
38
  * /device - DeviceService, useDeviceInfo
39
+ * /core - UnifiedCache, PermissionHandler, Repository utilities
39
40
  */
40
41
 
41
42
  if (__DEV__) {
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Camera Picker Strategy
3
+ *
4
+ * Strategy for capturing images/videos using device camera.
5
+ */
6
+
7
+ import * as ImagePicker from 'expo-image-picker';
8
+ import { PermissionManager } from '../../infrastructure/utils/PermissionManager';
9
+ import type { PickerStrategy, LaunchOptions } from './PickerStrategy';
10
+ import type { MediaLibraryPermission } from '../entities/Media';
11
+
12
+ /**
13
+ * Camera picker strategy configuration
14
+ */
15
+ export interface CameraPickerConfig {
16
+ mediaType: 'images' | 'videos';
17
+ }
18
+
19
+ /**
20
+ * Camera picker strategy implementation
21
+ */
22
+ export class CameraPickerStrategy implements PickerStrategy {
23
+ readonly name = 'CameraPicker';
24
+
25
+ constructor(
26
+ private config: CameraPickerConfig,
27
+ private permissionManager: typeof PermissionManager = PermissionManager
28
+ ) {}
29
+
30
+ async getPermission(): Promise<MediaLibraryPermission> {
31
+ return this.permissionManager.requestCameraPermission();
32
+ }
33
+
34
+ async launch(options: LaunchOptions): Promise<any> {
35
+ const mediaTypes =
36
+ this.config.mediaType === 'videos' ? ['videos'] : ['images'];
37
+
38
+ const launchOptions: ImagePicker.ImagePickerOptions = {
39
+ mediaTypes,
40
+ allowsEditing: options.allowsEditing ?? false,
41
+ quality: options.quality ?? 1,
42
+ base64: options.base64 ?? false,
43
+ };
44
+
45
+ // Add aspect ratio for images only
46
+ if (this.config.mediaType === 'images' && options.aspect) {
47
+ launchOptions.aspect = options.aspect;
48
+ }
49
+
50
+ // Add video-specific options
51
+ if (this.config.mediaType === 'videos') {
52
+ if (options.videoMaxDuration !== undefined) {
53
+ launchOptions.videoMaxDuration = options.videoMaxDuration;
54
+ }
55
+ if (options.videoMaxBitrate !== undefined) {
56
+ launchOptions.videoMaxBitrate = options.videoMaxBitrate;
57
+ }
58
+ if (options.videoQuality) {
59
+ launchOptions.videoQuality = options.videoQuality;
60
+ }
61
+ }
62
+
63
+ return ImagePicker.launchCameraAsync(launchOptions);
64
+ }
65
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Library Picker Strategy
3
+ *
4
+ * Strategy for picking images/videos from device gallery.
5
+ */
6
+
7
+ import * as ImagePicker from 'expo-image-picker';
8
+ import { PermissionManager } from '../../infrastructure/utils/PermissionManager';
9
+ import { MediaType } from '../entities/Media';
10
+ import type { PickerStrategy, LaunchOptions } from './PickerStrategy';
11
+ import type { MediaLibraryPermission } from '../entities/Media';
12
+
13
+ /**
14
+ * Helper to map media type to ImagePicker format
15
+ */
16
+ function mapMediaType(mediaType?: string): ImagePicker.MediaType[] {
17
+ if (!mediaType || mediaType === MediaType.ALL) {
18
+ return ['images', 'videos'];
19
+ }
20
+
21
+ if (mediaType === MediaType.VIDEO) {
22
+ return ['videos'];
23
+ }
24
+
25
+ return ['images'];
26
+ }
27
+
28
+ /**
29
+ * Library picker strategy implementation
30
+ */
31
+ export class LibraryPickerStrategy implements PickerStrategy {
32
+ readonly name = 'LibraryPicker';
33
+
34
+ constructor(
35
+ private permissionManager: typeof PermissionManager = PermissionManager
36
+ ) {}
37
+
38
+ async getPermission(): Promise<MediaLibraryPermission> {
39
+ return this.permissionManager.requestMediaLibraryPermission();
40
+ }
41
+
42
+ async launch(options: LaunchOptions): Promise<any> {
43
+ return ImagePicker.launchImageLibraryAsync({
44
+ mediaTypes: mapMediaType(options.mediaTypes),
45
+ allowsEditing: options.allowsEditing ?? false,
46
+ allowsMultipleSelection: options.allowsMultipleSelection ?? false,
47
+ aspect: options.aspect,
48
+ quality: options.quality ?? 1,
49
+ selectionLimit: options.selectionLimit ?? 1,
50
+ base64: options.base64 ?? false,
51
+ exif: options.exif ?? false,
52
+ });
53
+ }
54
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Media Picker Strategy Interface
3
+ *
4
+ * Strategy pattern for different media picker types.
5
+ * Allows MediaPickerService to support camera, video, and library pickers polymorphically.
6
+ */
7
+
8
+ import type { MediaLibraryPermission } from '../entities/Media';
9
+
10
+ /**
11
+ * Common picker options
12
+ */
13
+ export interface LaunchOptions {
14
+ allowsEditing?: boolean;
15
+ quality?: number;
16
+ aspect?: [number, number];
17
+ videoMaxDuration?: number;
18
+ videoMaxBitrate?: number;
19
+ videoQuality?: 'low' | 'medium' | 'high';
20
+ base64?: boolean;
21
+ exif?: boolean;
22
+ allowsMultipleSelection?: boolean;
23
+ selectionLimit?: number;
24
+ mediaTypes?: string;
25
+ maxFileSizeMB?: number;
26
+ }
27
+
28
+ /**
29
+ * Result from picker launch
30
+ */
31
+ export interface PickerLaunchResult {
32
+ canceled: boolean;
33
+ assets?: Array<{
34
+ uri: string;
35
+ width?: number;
36
+ height?: number;
37
+ type?: 'image' | 'video';
38
+ duration?: number;
39
+ fileSize?: number;
40
+ }>;
41
+ }
42
+
43
+ /**
44
+ * Media picker strategy interface
45
+ */
46
+ export interface PickerStrategy {
47
+ /**
48
+ * Get required permission for this picker type
49
+ */
50
+ getPermission(): Promise<MediaLibraryPermission>;
51
+
52
+ /**
53
+ * Launch the picker with options
54
+ */
55
+ launch(options: LaunchOptions): Promise<PickerLaunchResult>;
56
+
57
+ /**
58
+ * Strategy name for debugging
59
+ */
60
+ readonly name: string;
61
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Media Picker Strategies
3
+ *
4
+ * Strategy pattern implementations for different picker types.
5
+ */
6
+
7
+ export { PickerStrategy } from './PickerStrategy';
8
+ export type { LaunchOptions, PickerLaunchResult } from './PickerStrategy';
9
+
10
+ export { CameraPickerStrategy } from './CameraPickerStrategy';
11
+ export type { CameraPickerConfig } from './CameraPickerStrategy';
12
+
13
+ export { LibraryPickerStrategy } from './LibraryPickerStrategy';