@umituz/react-native-subscription 2.37.13 → 2.37.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 (133) hide show
  1. package/package.json +1 -1
  2. package/src/domains/credits/application/PurchaseMetadataGenerator.ts +1 -1
  3. package/src/domains/credits/application/credit-strategies/CreditAllocationOrchestrator.ts +1 -1
  4. package/src/domains/credits/application/creditDocumentHelpers.ts +0 -14
  5. package/src/domains/credits/presentation/deduct-credit/index.ts +0 -1
  6. package/src/domains/credits/presentation/useCredits.ts +1 -6
  7. package/src/domains/credits/utils/creditValidation.ts +3 -3
  8. package/src/domains/paywall/components/PaywallFeatures.tsx +1 -1
  9. package/src/domains/paywall/hooks/usePaywallActions.ts +1 -1
  10. package/src/domains/revenuecat/core/errors/RevenueCatError.ts +1 -14
  11. package/src/domains/revenuecat/core/errors/RevenueCatErrorHandler.ts +1 -1
  12. package/src/domains/revenuecat/core/types/RevenueCatTypes.ts +3 -3
  13. package/src/domains/revenuecat/infrastructure/services/ConfigurationStateManager.ts +8 -2
  14. package/src/domains/revenuecat/infrastructure/services/RevenueCatInitializer.ts +0 -2
  15. package/src/domains/subscription/application/initializer/BackgroundInitializer.ts +45 -16
  16. package/src/domains/subscription/application/initializer/index.ts +1 -1
  17. package/src/domains/subscription/core/SubscriptionStatus.ts +4 -10
  18. package/src/domains/subscription/core/SubscriptionStatusHandlers.ts +1 -1
  19. package/src/domains/subscription/infrastructure/handlers/PackageHandler.ts +0 -2
  20. package/src/domains/subscription/infrastructure/hooks/usePurchasePackage.ts +1 -1
  21. package/src/domains/subscription/infrastructure/hooks/useRevenueCatTrialEligibility.ts +1 -2
  22. package/src/domains/subscription/infrastructure/hooks/useSubscriptionQueries.ts +0 -4
  23. package/src/domains/subscription/infrastructure/services/OfferingsFetcher.ts +50 -22
  24. package/src/domains/subscription/infrastructure/services/RestoreHandler.ts +1 -1
  25. package/src/domains/subscription/infrastructure/services/RevenueCatService.ts +1 -2
  26. package/src/domains/subscription/infrastructure/services/revenueCatServiceInstance.ts +0 -4
  27. package/src/domains/subscription/infrastructure/utils/renewal/index.ts +1 -1
  28. package/src/domains/subscription/presentation/components/details/CreditRow.tsx +1 -1
  29. package/src/domains/subscription/presentation/components/details/DetailRow.tsx +1 -1
  30. package/src/domains/subscription/presentation/components/feedback/FeedbackOption.tsx +0 -2
  31. package/src/domains/subscription/presentation/components/feedback/FeedbackTextInput.tsx +1 -1
  32. package/src/domains/subscription/presentation/featureGateRefs.ts +1 -1
  33. package/src/domains/subscription/presentation/screens/components/CreditsList.tsx +2 -2
  34. package/src/domains/subscription/presentation/screens/components/SubscriptionHeader.tsx +0 -2
  35. package/src/domains/subscription/presentation/stores/index.ts +0 -5
  36. package/src/domains/subscription/presentation/stores/purchaseLoadingStore.ts +3 -7
  37. package/src/domains/subscription/presentation/useAuthAwarePurchase.ts +2 -8
  38. package/src/domains/subscription/presentation/useFeatureGate.ts +0 -2
  39. package/src/domains/subscription/presentation/usePaywallVisibility.ts +1 -1
  40. package/src/domains/subscription/utils/authGuards.ts +0 -23
  41. package/src/domains/subscription/utils/syncStatus.ts +1 -1
  42. package/src/domains/wallet/index.ts +0 -112
  43. package/src/domains/wallet/infrastructure/config/walletConfig.ts +1 -23
  44. package/src/domains/wallet/infrastructure/repositories/transaction/CollectionBuilder.ts +1 -1
  45. package/src/domains/wallet/infrastructure/repositories/transaction/index.ts +0 -9
  46. package/src/domains/wallet/presentation/components/BalanceCard.tsx +1 -1
  47. package/src/domains/wallet/presentation/components/TransactionItem.tsx +0 -2
  48. package/src/domains/wallet/presentation/components/TransactionList.tsx +3 -2
  49. package/src/domains/wallet/presentation/hooks/useTransactionHistory.ts +2 -2
  50. package/src/domains/wallet/presentation/hooks/useWallet.ts +2 -2
  51. package/src/shared/application/FeedbackService.ts +2 -2
  52. package/src/shared/infrastructure/SubscriptionEventBus.ts +1 -1
  53. package/src/shared/infrastructure/firestore/collectionUtils.ts +0 -7
  54. package/src/shared/infrastructure/firestore/resultUtils.ts +3 -39
  55. package/src/shared/presentation/layouts/ScreenLayout.tsx +1 -1
  56. package/src/shared/utils/numberUtils.core.ts +0 -27
  57. package/src/shared/utils/numberUtils.ts +1 -9
  58. package/src/shared/utils/validators.ts +0 -58
  59. package/src/domains/config/domain/entities/Plan.ts +0 -44
  60. package/src/domains/config/domain/index.ts +0 -2
  61. package/src/domains/config/domain/value-objects/Config.ts +0 -49
  62. package/src/domains/config/index.ts +0 -6
  63. package/src/domains/config/utils/planSelectors.ts +0 -56
  64. package/src/domains/paywall/components/FeatureItem.tsx +0 -50
  65. package/src/domains/paywall/components/FeatureList.tsx +0 -34
  66. package/src/domains/paywall/components/PaywallHeader.tsx +0 -112
  67. package/src/domains/paywall/hooks/usePaywallTranslations.ts +0 -78
  68. package/src/domains/paywall/hooks/useSubscriptionModal.ts +0 -45
  69. package/src/domains/paywall/index.ts +0 -13
  70. package/src/domains/revenuecat/core/constants/RevenueCatConstants.ts +0 -201
  71. package/src/domains/revenuecat/core/constants/index.ts +0 -5
  72. package/src/domains/revenuecat/core/customerInfoHelpers.ts +0 -21
  73. package/src/domains/revenuecat/core/index.ts +0 -7
  74. package/src/domains/revenuecat/index.ts +0 -7
  75. package/src/domains/revenuecat/infrastructure/index.ts +0 -5
  76. package/src/domains/revenuecat/infrastructure/services/index.ts +0 -7
  77. package/src/domains/subscription/infrastructure/hooks/customer-info/index.ts +0 -2
  78. package/src/domains/subscription/infrastructure/hooks/customer-info/types.ts +0 -9
  79. package/src/domains/subscription/infrastructure/hooks/customer-info/useCustomerInfo.ts +0 -52
  80. package/src/domains/subscription/infrastructure/hooks/useInitializeSubscription.ts +0 -30
  81. package/src/domains/subscription/infrastructure/hooks/usePaywallFlow.ts +0 -78
  82. package/src/domains/subscription/infrastructure/hooks/useRevenueCat.ts +0 -119
  83. package/src/domains/subscription/presentation/components/feedback/FeedbackConstants.ts +0 -6
  84. package/src/domains/subscription/presentation/screens/components/SubscriptionActions.tsx +0 -56
  85. package/src/domains/subscription/utils/dateFormatters.ts +0 -28
  86. package/src/domains/wallet/domain/entities/CreditCost.ts +0 -45
  87. package/src/domains/wallet/domain/entities/README.md +0 -41
  88. package/src/domains/wallet/domain/errors/README.md +0 -40
  89. package/src/domains/wallet/domain/errors/WalletError.ts +0 -17
  90. package/src/domains/wallet/domain/errors/WalletError.types.ts +0 -30
  91. package/src/domains/wallet/domain/errors/WalletErrorClasses.ts +0 -82
  92. package/src/domains/wallet/domain/errors/WalletErrorFactory.ts +0 -24
  93. package/src/domains/wallet/domain/errors/WalletErrorMessages.ts +0 -17
  94. package/src/domains/wallet/domain/types/credit-cost.types.ts +0 -86
  95. package/src/domains/wallet/domain/types/index.ts +0 -33
  96. package/src/domains/wallet/domain/types/wallet.types.ts +0 -50
  97. package/src/domains/wallet/infrastructure/services/product-metadata/CacheManager.ts +0 -30
  98. package/src/domains/wallet/infrastructure/services/product-metadata/FirebaseFetcher.ts +0 -17
  99. package/src/domains/wallet/infrastructure/services/product-metadata/ProductMetadataService.ts +0 -57
  100. package/src/domains/wallet/infrastructure/services/product-metadata/ServiceManager.ts +0 -29
  101. package/src/domains/wallet/infrastructure/services/product-metadata/index.ts +0 -7
  102. package/src/domains/wallet/presentation/hooks/index.ts +0 -8
  103. package/src/domains/wallet/presentation/hooks/useProductMetadata.ts +0 -72
  104. package/src/domains/wallet/utils/index.ts +0 -1
  105. package/src/shared/application/ActivationHandler.ts +0 -108
  106. package/src/shared/application/ports/ISubscriptionService.ts +0 -27
  107. package/src/shared/infrastructure/index.ts +0 -6
  108. package/src/shared/infrastructure/react-query/queryInvalidation.ts +0 -46
  109. package/src/shared/presentation/hooks/index.ts +0 -6
  110. package/src/shared/presentation/hooks/useAsyncState.ts +0 -72
  111. package/src/shared/presentation/hooks/useServiceCall.ts +0 -77
  112. package/src/shared/types/ReactTypes.ts +0 -80
  113. package/src/shared/utils/InsufficientCreditsError.ts +0 -32
  114. package/src/shared/utils/Logger.ts +0 -81
  115. package/src/shared/utils/SubscriptionConfig.ts +0 -15
  116. package/src/shared/utils/SubscriptionError.ts +0 -47
  117. package/src/shared/utils/appValidators.ts +0 -38
  118. package/src/shared/utils/arrayUtils.core.ts +0 -81
  119. package/src/shared/utils/arrayUtils.query.ts +0 -118
  120. package/src/shared/utils/arrayUtils.transforms.ts +0 -116
  121. package/src/shared/utils/arrayUtils.ts +0 -19
  122. package/src/shared/utils/errorUtils.ts +0 -32
  123. package/src/shared/utils/index.ts +0 -14
  124. package/src/shared/utils/numberUtils.aggregate.ts +0 -35
  125. package/src/shared/utils/numberUtils.format.ts +0 -42
  126. package/src/shared/utils/numberUtils.math.ts +0 -48
  127. package/src/shared/utils/queryKeyFactory.ts +0 -9
  128. package/src/shared/utils/stringUtils.case.ts +0 -64
  129. package/src/shared/utils/stringUtils.check.ts +0 -65
  130. package/src/shared/utils/stringUtils.format.ts +0 -84
  131. package/src/shared/utils/stringUtils.generate.ts +0 -47
  132. package/src/shared/utils/stringUtils.modify.ts +0 -67
  133. package/src/shared/utils/stringUtils.ts +0 -10
@@ -1,77 +0,0 @@
1
- /**
2
- * useServiceCall Hook
3
- * Shared hook for handling service calls with loading, error, and success states
4
- */
5
-
6
- import { useState, useCallback, useRef, useEffect } from "react";
7
- import { normalizeError } from "../../utils/errorUtils";
8
-
9
- export interface ServiceCallState<T> {
10
- data: T | null;
11
- isLoading: boolean;
12
- error: Error | null;
13
- }
14
-
15
- export interface UseServiceCallOptions<T> {
16
- onSuccess?: (data: T) => void;
17
- onError?: (error: Error) => void;
18
- onComplete?: () => void;
19
- }
20
-
21
- export interface ServiceCallResult<T> {
22
- data: T | null;
23
- isLoading: boolean;
24
- error: Error | null;
25
- execute: () => Promise<void>;
26
- reset: () => void;
27
- }
28
-
29
- export function useServiceCall<T>(
30
- serviceFn: () => Promise<T>,
31
- options: UseServiceCallOptions<T> = {}
32
- ): ServiceCallResult<T> {
33
- const { onSuccess, onError, onComplete } = options;
34
- const [state, setState] = useState<ServiceCallState<T>>({
35
- data: null,
36
- isLoading: false,
37
- error: null,
38
- });
39
-
40
- const onSuccessRef = useRef(onSuccess);
41
- const onErrorRef = useRef(onError);
42
- const onCompleteRef = useRef(onComplete);
43
-
44
- useEffect(() => {
45
- onSuccessRef.current = onSuccess;
46
- onErrorRef.current = onError;
47
- onCompleteRef.current = onComplete;
48
- });
49
-
50
- const execute = useCallback(async () => {
51
- setState({ data: null, isLoading: true, error: null });
52
-
53
- try {
54
- const data = await serviceFn();
55
- setState({ data, isLoading: false, error: null });
56
- onSuccessRef.current?.(data);
57
- } catch (error) {
58
- const errorObj = normalizeError(error, "Service call failed");
59
- setState({ data: null, isLoading: false, error: errorObj });
60
- onErrorRef.current?.(errorObj);
61
- } finally {
62
- onCompleteRef.current?.();
63
- }
64
- }, [serviceFn]);
65
-
66
- const reset = useCallback(() => {
67
- setState({ data: null, isLoading: false, error: null });
68
- }, []);
69
-
70
- return {
71
- data: state.data,
72
- isLoading: state.isLoading,
73
- error: state.error,
74
- execute,
75
- reset,
76
- };
77
- }
@@ -1,80 +0,0 @@
1
- /**
2
- * Shared React Types
3
- * Common type definitions for React components and hooks
4
- */
5
-
6
- export type VoidCallback = () => void;
7
- export type AsyncCallback = () => Promise<void> | Promise<void>;
8
-
9
- export type EventHandler<T = void> = (event: T) => void;
10
- export type AsyncEventHandler<T = void> = (event: T) => Promise<void>;
11
-
12
- export interface LoadingState {
13
- isLoading: boolean;
14
- isRefreshing: boolean;
15
- }
16
-
17
- export interface ErrorState {
18
- error: Error | null;
19
- hasError: boolean;
20
- }
21
-
22
- export interface PaginationState {
23
- page: number;
24
- perPage: number;
25
- total: number;
26
- hasMore: boolean;
27
- }
28
-
29
- export interface ScreenProps<T = unknown> {
30
- route: {
31
- params?: T;
32
- };
33
- navigation: any;
34
- }
35
-
36
- export type ButtonProps = {
37
- onPress: EventHandler | AsyncEventHandler;
38
- disabled?: boolean;
39
- loading?: boolean;
40
- };
41
-
42
- export interface SelectableItem {
43
- id: string;
44
- selected: boolean;
45
- }
46
-
47
- export interface FormFieldProps<T> {
48
- value: T;
49
- onChange: (value: T) => void;
50
- error?: string;
51
- label?: string;
52
- placeholder?: string;
53
- disabled?: boolean;
54
- }
55
-
56
- export interface ListItemProps<T> {
57
- item: T;
58
- index: number;
59
- onPress?: (item: T, index: number) => void;
60
- onLongPress?: (item: T, index: number) => void;
61
- }
62
-
63
- export interface SearchState {
64
- query: string;
65
- results: unknown[];
66
- isSearching: boolean;
67
- }
68
-
69
- export interface TabItem {
70
- id: string;
71
- title: string;
72
- icon?: string;
73
- badge?: number | string;
74
- }
75
-
76
- export interface ModalProps {
77
- visible: boolean;
78
- onClose: () => void;
79
- title?: string;
80
- }
@@ -1,32 +0,0 @@
1
- /**
2
- * InsufficientCreditsError
3
- *
4
- * Thrown when user doesn't have enough credits for an operation.
5
- * Silently handled - triggers paywall display.
6
- */
7
-
8
- export class InsufficientCreditsError extends Error {
9
- public readonly requiredCredits: number;
10
- public readonly availableCredits: number;
11
- public readonly operationType: string;
12
-
13
- constructor(
14
- requiredCredits: number,
15
- availableCredits: number,
16
- operationType: string,
17
- ) {
18
- super(
19
- `Insufficient credits: ${availableCredits} available, ${requiredCredits} required`,
20
- );
21
- this.name = "InsufficientCreditsError";
22
- this.requiredCredits = requiredCredits;
23
- this.availableCredits = availableCredits;
24
- this.operationType = operationType;
25
-
26
- Object.setPrototypeOf(this, InsufficientCreditsError.prototype);
27
- }
28
-
29
- get deficit(): number {
30
- return this.requiredCredits - this.availableCredits;
31
- }
32
- }
@@ -1,81 +0,0 @@
1
- /**
2
- * Subscription Logger
3
- * Centralized logging utility for the subscription package.
4
- * All logs are disabled - no logging.
5
- */
6
-
7
- export type LogLevel = "debug" | "info" | "warn" | "error";
8
-
9
- export interface LogMetadata {
10
- [key: string]: unknown;
11
- }
12
-
13
- /** Log categories for filtering and grouping */
14
- export const LOG_CATEGORY = {
15
- REVENUECAT: "RevenueCat",
16
- CREDITS: "Credits",
17
- TRIAL: "Trial",
18
- PURCHASE: "Purchase",
19
- FEATURE_GATE: "FeatureGate",
20
- SUBSCRIPTION: "Subscription",
21
- SYNC: "Sync",
22
- } as const;
23
-
24
- export type LogCategory = (typeof LOG_CATEGORY)[keyof typeof LOG_CATEGORY];
25
-
26
- /**
27
- * Development-only logger that automatically respects __DEV__ flag.
28
- * All methods are no-ops - logging is disabled.
29
- */
30
- class SubscriptionLogger {
31
- /** Enable or disable all logging */
32
- setEnabled(_enabled: boolean): void {
33
- }
34
-
35
- /** Enable logging for specific categories only */
36
- setCategories(_categories: LogCategory[]): void {
37
- }
38
-
39
- /** Clear category filter (log all categories) */
40
- clearCategories(): void {
41
- }
42
-
43
- debug(_category: LogCategory, _message: string, _metadata?: LogMetadata): void {
44
- }
45
-
46
- info(_category: LogCategory, _message: string, _metadata?: LogMetadata): void {
47
- }
48
-
49
- warn(_category: LogCategory, _message: string, _metadata?: LogMetadata): void {
50
- }
51
-
52
- error(_category: LogCategory, _message: string, _error?: unknown, _metadata?: LogMetadata): void {
53
- }
54
-
55
- /** Log purchase flow events */
56
- purchase(_message: string, _metadata?: LogMetadata): void {
57
- }
58
-
59
- /** Log credits-related events */
60
- credits(_message: string, _metadata?: LogMetadata): void {
61
- }
62
-
63
- /** Log trial-related events */
64
- trial(_message: string, _metadata?: LogMetadata): void {
65
- }
66
-
67
- /** Log RevenueCat SDK events */
68
- revenueCat(_message: string, _metadata?: LogMetadata): void {
69
- }
70
-
71
- /** Log feature gate events */
72
- featureGate(_message: string, _metadata?: LogMetadata): void {
73
- }
74
-
75
- /** Log sync operations */
76
- sync(_message: string, _metadata?: LogMetadata): void {
77
- }
78
- }
79
-
80
- /** Singleton logger instance */
81
- export const Logger = new SubscriptionLogger();
@@ -1,15 +0,0 @@
1
- /**
2
- * Subscription Config Value Object
3
- */
4
-
5
- import { ISubscriptionRepository } from "../application/ports/ISubscriptionRepository";
6
- import { SubscriptionStatus } from "../../domains/subscription/core/SubscriptionStatus";
7
-
8
- export interface SubscriptionConfig {
9
- repository: ISubscriptionRepository;
10
- revenueCatApiKey?: string;
11
- entitlements?: string[];
12
- debugMode?: boolean;
13
- onStatusChanged?: (userId: string, status: SubscriptionStatus) => Promise<void> | void;
14
- onError?: (error: Error, operation: string) => Promise<void> | void;
15
- }
@@ -1,47 +0,0 @@
1
- /**
2
- * Subscription Error
3
- * Custom error class for subscription-related errors
4
- */
5
-
6
- import { BaseError } from "./BaseError";
7
-
8
- export class SubscriptionError extends BaseError {
9
- constructor(message: string, code: string = 'SUBSCRIPTION_ERROR', cause?: Error) {
10
- super(message, code, cause);
11
- this.name = 'SubscriptionError';
12
- }
13
-
14
- static notFound(message: string = 'Subscription not found', cause?: Error): SubscriptionError {
15
- return new SubscriptionError(message, 'SUBSCRIPTION_NOT_FOUND', cause);
16
- }
17
-
18
- static expired(message: string = 'Subscription has expired', cause?: Error): SubscriptionError {
19
- return new SubscriptionError(message, 'SUBSCRIPTION_EXPIRED', cause);
20
- }
21
-
22
- static purchaseFailed(message: string = 'Purchase failed', cause?: Error): SubscriptionError {
23
- return new SubscriptionError(message, 'PURCHASE_FAILED', cause);
24
- }
25
-
26
- static restoreFailed(message: string = 'Restore failed', cause?: Error): SubscriptionError {
27
- return new SubscriptionError(message, 'RESTORE_FAILED', cause);
28
- }
29
-
30
- static networkError(message: string = 'Network error', cause?: Error): SubscriptionError {
31
- return new SubscriptionError(message, 'NETWORK_ERROR', cause);
32
- }
33
- }
34
-
35
- export class SubscriptionRepositoryError extends BaseError {
36
- constructor(message: string, code: string = 'REPOSITORY_ERROR', cause?: Error) {
37
- super(message, code, cause);
38
- this.name = 'SubscriptionRepositoryError';
39
- }
40
- }
41
-
42
- export class SubscriptionValidationError extends BaseError {
43
- constructor(message: string, code: string = 'VALIDATION_ERROR', cause?: Error) {
44
- super(message, code, cause);
45
- this.name = 'SubscriptionValidationError';
46
- }
47
- }
@@ -1,38 +0,0 @@
1
- import {
2
- isNonEmptyString,
3
- isValidNumber,
4
- isPositiveNumber,
5
- isNonNegativeNumber,
6
- isInteger,
7
- } from "./validators";
8
-
9
- export function isValidCreditAmount(value: unknown): value is number {
10
- return isInteger(value) && isNonNegativeNumber(value);
11
- }
12
-
13
- export function isValidPrice(value: unknown): value is number {
14
- if (!isPositiveNumber(value)) return false;
15
- const decimalPlaces = (value.toString().split(".")[1] || "").length;
16
- return decimalPlaces <= 2;
17
- }
18
-
19
- export function isValidProductId(value: unknown): value is string {
20
- return isNonEmptyString(value) && /^[a-zA-Z0-9._-]+$/.test(value);
21
- }
22
-
23
- export function isValidUserId(value: unknown): value is string {
24
- return isNonEmptyString(value);
25
- }
26
-
27
- export function sanitizeString(value: unknown): string | null {
28
- if (value === null || value === undefined) return null;
29
- return String(value).trim().replace(/\s+/g, " ");
30
- }
31
-
32
- export function sanitizeNumber(value: unknown, defaultValue: number = 0): number {
33
- return isValidNumber(value) ? value : defaultValue;
34
- }
35
-
36
- export function isOneOf<T>(value: unknown, allowedValues: readonly T[]): value is T {
37
- return allowedValues.includes(value as T);
38
- }
@@ -1,81 +0,0 @@
1
- /**
2
- * Array Utilities - Core Operations
3
- * Basic array manipulation functions
4
- */
5
-
6
- /**
7
- * Check if array is empty
8
- */
9
- export function isEmpty<T>(arr: readonly T[] | null | undefined): boolean {
10
- return !arr || arr.length === 0;
11
- }
12
-
13
- /**
14
- * Check if array has elements
15
- */
16
- export function isNotEmpty<T>(arr: readonly T[] | null | undefined): boolean {
17
- return !isEmpty(arr);
18
- }
19
-
20
- /**
21
- * Get first element of array or null
22
- */
23
- export function first<T>(arr: readonly T[] | null | undefined): T | null {
24
- if (!arr || arr.length === 0) return null;
25
- return arr[0] ?? null;
26
- }
27
-
28
- /**
29
- * Get last element of array or null
30
- */
31
- export function last<T>(arr: readonly T[] | null | undefined): T | null {
32
- if (!arr || arr.length === 0) return null;
33
- return arr[arr.length - 1] ?? null;
34
- }
35
-
36
- /**
37
- * Get nth element of array or null
38
- */
39
- export function nth<T>(arr: readonly T[], index: number): T | null {
40
- if (index < 0) index = arr.length + index;
41
- if (index < 0 || index >= arr.length) return null;
42
- return arr[index] ?? null;
43
- }
44
-
45
- /**
46
- * Remove first element from array
47
- */
48
- export function removeFirst<T>(arr: T[]): T[] {
49
- return arr.slice(1);
50
- }
51
-
52
- /**
53
- * Remove last element from array
54
- */
55
- export function removeLast<T>(arr: T[]): T[] {
56
- return arr.slice(0, -1);
57
- }
58
-
59
- /**
60
- * Remove element at index
61
- */
62
- export function removeAt<T>(arr: readonly T[], index: number): T[] {
63
- return arr.filter((_, i) => i !== index);
64
- }
65
-
66
- /**
67
- * Remove elements that match a predicate
68
- */
69
- export function removeWhere<T>(
70
- arr: readonly T[],
71
- predicate: (item: T, index: number) => boolean
72
- ): T[] {
73
- return arr.filter((item, index) => !predicate(item, index));
74
- }
75
-
76
- /**
77
- * Unique array elements (removes duplicates)
78
- */
79
- export function unique<T>(arr: readonly T[]): T[] {
80
- return Array.from(new Set(arr));
81
- }
@@ -1,118 +0,0 @@
1
- /**
2
- * Array Utilities - Query Operations
3
- * Array searching, filtering, and grouping functions
4
- */
5
-
6
- /**
7
- * Group array elements by a key function
8
- */
9
- export function groupBy<T, K extends string | number | symbol>(
10
- arr: readonly T[],
11
- keyFn: (item: T, index: number) => K
12
- ): Record<K, T[]> {
13
- return arr.reduce((result, item, index) => {
14
- const key = keyFn(item, index);
15
- if (!result[key]) {
16
- result[key] = [];
17
- }
18
- result[key].push(item);
19
- return result;
20
- }, {} as Record<K, T[]>);
21
- }
22
-
23
- /**
24
- * Unique array elements by a key function
25
- */
26
- export function uniqueBy<T, K>(arr: readonly T[], keyFn: (item: T) => K): T[] {
27
- const seen = new Set<K>();
28
- return arr.filter((item) => {
29
- const key = keyFn(item);
30
- if (seen.has(key)) return false;
31
- seen.add(key);
32
- return true;
33
- });
34
- }
35
-
36
- /**
37
- * Shuffle array (Fisher-Yates algorithm)
38
- */
39
- export function shuffle<T>(arr: readonly T[]): T[] {
40
- const result = [...arr];
41
- for (let i = result.length - 1; i > 0; i--) {
42
- const j = Math.floor(Math.random() * (i + 1));
43
- const temp = result[i]!;
44
- result[i] = result[j]!;
45
- result[j] = temp;
46
- }
47
- return result;
48
- }
49
-
50
- /**
51
- * Sort array by a key function
52
- */
53
- export function sortBy<T>(
54
- arr: readonly T[],
55
- keyFn: (item: T) => string | number,
56
- order: "asc" | "desc" = "asc"
57
- ): T[] {
58
- return [...arr].sort((a, b) => {
59
- const keyA = keyFn(a);
60
- const keyB = keyFn(b);
61
- if (keyA < keyB) return order === "asc" ? -1 : 1;
62
- if (keyA > keyB) return order === "asc" ? 1 : -1;
63
- return 0;
64
- });
65
- }
66
-
67
- /**
68
- * Pick random element(s) from array
69
- */
70
- export function sample<T>(arr: readonly T[], count: number = 1): T[] {
71
- if (arr.length === 0) return [];
72
- const shuffled = shuffle([...arr]);
73
- return shuffled.slice(0, Math.min(count, arr.length));
74
- }
75
-
76
- /**
77
- * Find intersection of two arrays
78
- */
79
- export function intersection<T>(arr1: readonly T[], arr2: readonly T[]): T[] {
80
- const set2 = new Set(arr2);
81
- return arr1.filter((item) => set2.has(item));
82
- }
83
-
84
- /**
85
- * Find difference of two arrays (elements in arr1 but not in arr2)
86
- */
87
- export function difference<T>(arr1: readonly T[], arr2: readonly T[]): T[] {
88
- const set2 = new Set(arr2);
89
- return arr1.filter((item) => !set2.has(item));
90
- }
91
-
92
- /**
93
- * Find symmetric difference of two arrays (elements in either array but not both)
94
- */
95
- export function symmetricDifference<T>(arr1: readonly T[], arr2: readonly T[]): T[] {
96
- const set1 = new Set(arr1);
97
- const set2 = new Set(arr2);
98
- return [
99
- ...arr1.filter((item) => !set2.has(item)),
100
- ...arr2.filter((item) => !set1.has(item)),
101
- ];
102
- }
103
-
104
- /**
105
- * Check if array contains all elements of another array
106
- */
107
- export function containsAll<T>(arr: readonly T[], values: readonly T[]): boolean {
108
- const arrSet = new Set(arr);
109
- return values.every((value) => arrSet.has(value));
110
- }
111
-
112
- /**
113
- * Check if array contains any element of another array
114
- */
115
- export function containsAny<T>(arr: readonly T[], values: readonly T[]): boolean {
116
- const arrSet = new Set(arr);
117
- return values.some((value) => arrSet.has(value));
118
- }
@@ -1,116 +0,0 @@
1
- /**
2
- * Array Utilities - Transformations
3
- * Array transformation and manipulation functions
4
- */
5
-
6
- /**
7
- * Chunk array into smaller arrays of specified size
8
- */
9
- export function chunk<T>(arr: readonly T[], size: number): T[][] {
10
- if (size <= 0) return [];
11
- const result: T[][] = [];
12
- for (let i = 0; i < arr.length; i += size) {
13
- result.push(arr.slice(i, i + size));
14
- }
15
- return result;
16
- }
17
-
18
- /**
19
- * Flatten array one level deep
20
- */
21
- export function flatten<T>(arr: readonly (readonly T[] | T)[]): T[] {
22
- const result: T[] = [];
23
- for (const item of arr) {
24
- if (Array.isArray(item)) {
25
- result.push(...item);
26
- } else if (item !== undefined) {
27
- result.push(item as T);
28
- }
29
- }
30
- return result;
31
- }
32
-
33
- /**
34
- * Flatten array recursively
35
- */
36
- export function flattenDeep<T>(arr: readonly unknown[]): T[] {
37
- const result: T[] = [];
38
- const stack = [...arr];
39
-
40
- while (stack.length > 0) {
41
- const item = stack.shift();
42
- if (Array.isArray(item)) {
43
- stack.unshift(...item);
44
- } else if (item !== undefined) {
45
- result.push(item as T);
46
- }
47
- }
48
-
49
- return result;
50
- }
51
-
52
- /**
53
- * Zip two arrays together
54
- */
55
- export function zip<T, U>(arr1: readonly T[], arr2: readonly U[]): [T, U][] {
56
- const length = Math.min(arr1.length, arr2.length);
57
- const result: [T, U][] = [];
58
- for (let i = 0; i < length; i++) {
59
- result.push([arr1[i]!, arr2[i]!]);
60
- }
61
- return result;
62
- }
63
-
64
- /**
65
- * Partition array into two arrays based on predicate
66
- */
67
- export function partition<T>(
68
- arr: readonly T[],
69
- predicate: (item: T, index: number) => boolean
70
- ): [T[], T[]] {
71
- const truthy: T[] = [];
72
- const falsy: T[] = [];
73
-
74
- for (let i = 0; i < arr.length; i++) {
75
- const item = arr[i];
76
- if (item !== undefined) {
77
- if (predicate(item, i)) {
78
- truthy.push(item);
79
- } else {
80
- falsy.push(item);
81
- }
82
- }
83
- }
84
-
85
- return [truthy, falsy];
86
- }
87
-
88
- /**
89
- * Move element from one index to another
90
- */
91
- export function move<T>(arr: readonly T[], from: number, to: number): T[] {
92
- if (from < 0 || from >= arr.length || to < 0 || to >= arr.length) {
93
- return [...arr];
94
- }
95
- const result = [...arr];
96
- const element = result[from];
97
- if (element === undefined) return result;
98
-
99
- result.splice(from, 1);
100
- result.splice(to, 0, element);
101
- return result;
102
- }
103
-
104
- /**
105
- * Swap two elements in array
106
- */
107
- export function swap<T>(arr: readonly T[], index1: number, index2: number): T[] {
108
- if (index1 < 0 || index1 >= arr.length || index2 < 0 || index2 >= arr.length) {
109
- return [...arr];
110
- }
111
- const result = [...arr];
112
- const temp = result[index1];
113
- result[index1] = result[index2]!;
114
- result[index2] = temp!;
115
- return result;
116
- }
@@ -1,19 +0,0 @@
1
- /**
2
- * Array Utilities
3
- * Re-exports all array utility modules
4
- */
5
-
6
- export * from "./arrayUtils.core";
7
- export * from "./arrayUtils.transforms";
8
- export * from "./arrayUtils.query";
9
-
10
- /**
11
- * Create an array of numbers from start to end (inclusive)
12
- */
13
- export function range(start: number, end: number, step: number = 1): number[] {
14
- const result: number[] = [];
15
- for (let i = start; step > 0 ? i <= end : i >= end; i += step) {
16
- result.push(i);
17
- }
18
- return result;
19
- }