@umituz/react-native-ai-creations 1.0.0 → 1.0.2

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/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-creations",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "AI-generated creations gallery with filtering, sharing, and management for React Native apps",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
7
7
  "scripts": {
8
8
  "typecheck": "tsc --noEmit",
9
9
  "lint": "tsc --noEmit",
10
+ "version:patch": "npm version patch -m 'chore: release v%s'",
10
11
  "version:minor": "npm version minor -m 'chore: release v%s'",
11
12
  "version:major": "npm version major -m 'chore: release v%s'"
12
13
  },
@@ -29,6 +30,7 @@
29
30
  "peerDependencies": {
30
31
  "@tanstack/react-query": ">=5.0.0",
31
32
  "@umituz/react-native-design-system": "latest",
33
+ "@umituz/react-native-firestore": "latest",
32
34
  "@umituz/react-native-sharing": "latest",
33
35
  "firebase": ">=11.0.0",
34
36
  "react": ">=18.2.0",
@@ -3,6 +3,8 @@
3
3
  * Defines the configuration for creations feature
4
4
  */
5
5
 
6
+ import type { Creation, CreationDocument } from "../entities/Creation";
7
+
6
8
  export interface CreationType {
7
9
  readonly id: string;
8
10
  readonly labelKey: string;
@@ -20,12 +22,31 @@ export interface CreationsTranslations {
20
22
  readonly filterAll: string;
21
23
  }
22
24
 
25
+ /**
26
+ * Path builder function type
27
+ * Allows apps to define custom Firestore path structures
28
+ * @example
29
+ * // Default: users/{userId}/creations
30
+ * pathBuilder: (userId) => ["users", userId, "creations"]
31
+ * // Alternative: creations/{userId}/items
32
+ * pathBuilder: (userId) => ["creations", userId, "items"]
33
+ */
34
+ export type PathBuilder = (userId: string) => string[];
35
+
36
+ /**
37
+ * Document mapper function type
38
+ * Allows apps to map their specific document structure to Creation
39
+ */
40
+ export type DocumentMapper = (id: string, data: CreationDocument) => Creation;
41
+
23
42
  export interface CreationsConfig {
24
43
  readonly collectionName: string;
25
44
  readonly types: readonly CreationType[];
26
45
  readonly translations: CreationsTranslations;
27
46
  readonly maxThumbnails?: number;
28
47
  readonly gridColumns?: number;
48
+ readonly pathBuilder?: PathBuilder;
49
+ readonly documentMapper?: DocumentMapper;
29
50
  }
30
51
 
31
52
  export const DEFAULT_TRANSLATIONS: CreationsTranslations = {
@@ -6,5 +6,7 @@ export type {
6
6
  CreationType,
7
7
  CreationsTranslations,
8
8
  CreationsConfig,
9
+ PathBuilder,
10
+ DocumentMapper,
9
11
  } from "./CreationsConfig";
10
12
  export { DEFAULT_TRANSLATIONS, DEFAULT_CONFIG } from "./CreationsConfig";
package/src/index.ts CHANGED
@@ -3,6 +3,14 @@
3
3
  *
4
4
  * AI-generated creations gallery with filtering, sharing, and management
5
5
  *
6
+ * Architecture:
7
+ * - Extends BaseRepository from @umituz/react-native-firestore
8
+ * - Fully dynamic path structure (configurable per app)
9
+ * - Fully dynamic document mapping (configurable per app)
10
+ * - App-agnostic: Works with any app, no app-specific code
11
+ *
12
+ * This package is designed to be used across hundreds of apps.
13
+ *
6
14
  * Usage:
7
15
  * import {
8
16
  * CreationsGalleryScreen,
@@ -27,6 +35,8 @@ export type {
27
35
  CreationType,
28
36
  CreationsTranslations,
29
37
  CreationsConfig,
38
+ PathBuilder,
39
+ DocumentMapper,
30
40
  } from "./domain/value-objects";
31
41
  export { DEFAULT_TRANSLATIONS, DEFAULT_CONFIG } from "./domain/value-objects";
32
42
 
@@ -40,7 +50,10 @@ export type { ICreationsRepository } from "./domain/repositories";
40
50
  // INFRASTRUCTURE LAYER
41
51
  // =============================================================================
42
52
 
43
- export { CreationsRepository } from "./infrastructure/repositories";
53
+ export {
54
+ CreationsRepository,
55
+ type RepositoryOptions,
56
+ } from "./infrastructure/repositories";
44
57
  export { createCreationsRepository } from "./infrastructure/adapters";
45
58
 
46
59
  // =============================================================================
@@ -1,15 +1,54 @@
1
1
  /**
2
2
  * Repository Factory
3
3
  * Creates repository instance with given configuration
4
+ *
5
+ * Architecture:
6
+ * - Factory pattern for repository creation
7
+ * - Supports dynamic path structure per app
8
+ * - Supports custom document mapping per app
9
+ * - App-agnostic: No Firestore instance needed (BaseRepository handles it)
10
+ *
11
+ * This factory is designed to be used across hundreds of apps.
4
12
  */
5
13
 
6
- import type { Firestore } from "firebase/firestore";
7
- import { CreationsRepository } from "../repositories/CreationsRepository";
14
+ import {
15
+ CreationsRepository,
16
+ type RepositoryOptions,
17
+ } from "../repositories/CreationsRepository";
8
18
  import type { ICreationsRepository } from "../../domain/repositories/ICreationsRepository";
9
19
 
20
+ /**
21
+ * Creates a new CreationsRepository instance
22
+ *
23
+ * @param collectionName - Firestore collection name
24
+ * @param options - Optional repository configuration
25
+ * @returns ICreationsRepository instance
26
+ *
27
+ * @example
28
+ * // Basic usage with default path (users/{userId}/photos)
29
+ * const repo = createCreationsRepository("photos");
30
+ *
31
+ * @example
32
+ * // Custom path structure
33
+ * const repo = createCreationsRepository("creations", {
34
+ * pathBuilder: (userId) => ["gallery", userId, "items"],
35
+ * });
36
+ *
37
+ * @example
38
+ * // Custom document mapper
39
+ * const repo = createCreationsRepository("photos", {
40
+ * documentMapper: (id, data) => ({
41
+ * id,
42
+ * uri: data.imageUrl,
43
+ * type: data.category,
44
+ * createdAt: data.timestamp?.toDate() || new Date(),
45
+ * isShared: data.public ?? false,
46
+ * }),
47
+ * });
48
+ */
10
49
  export function createCreationsRepository(
11
- db: Firestore | null,
12
50
  collectionName: string,
51
+ options?: RepositoryOptions,
13
52
  ): ICreationsRepository {
14
- return new CreationsRepository(db, collectionName);
53
+ return new CreationsRepository(collectionName, options);
15
54
  }
@@ -1,6 +1,14 @@
1
1
  /**
2
2
  * Creations Repository Implementation
3
- * Firestore operations for user creations
3
+ * Extends BaseRepository from @umituz/react-native-firestore
4
+ *
5
+ * Architecture:
6
+ * - Extends BaseRepository for centralized database access
7
+ * - Fully dynamic path structure (configurable per app)
8
+ * - Fully dynamic document mapping (configurable per app)
9
+ * - App-agnostic: Works with any app, no app-specific code
10
+ *
11
+ * This class is designed to be used across hundreds of apps.
4
12
  */
5
13
 
6
14
  declare const __DEV__: boolean;
@@ -13,21 +21,72 @@ import {
13
21
  updateDoc,
14
22
  query,
15
23
  orderBy,
16
- type Firestore,
17
24
  } from "firebase/firestore";
25
+ import { BaseRepository } from "@umituz/react-native-firestore";
18
26
  import type { ICreationsRepository } from "../../domain/repositories/ICreationsRepository";
19
27
  import type { Creation, CreationDocument } from "../../domain/entities/Creation";
20
28
  import { mapDocumentToCreation } from "../../domain/entities/Creation";
29
+ import type {
30
+ PathBuilder,
31
+ DocumentMapper,
32
+ } from "../../domain/value-objects/CreationsConfig";
33
+
34
+ /**
35
+ * Repository options for dynamic configuration
36
+ * Apps can customize path structure and document mapping
37
+ */
38
+ export interface RepositoryOptions {
39
+ /**
40
+ * Custom path builder function
41
+ * @example (userId) => ["users", userId, "photos"]
42
+ * @example (userId) => ["creations", userId, "items"]
43
+ */
44
+ readonly pathBuilder?: PathBuilder;
45
+
46
+ /**
47
+ * Custom document mapper function
48
+ * Maps Firestore documents to Creation entity
49
+ */
50
+ readonly documentMapper?: DocumentMapper;
51
+ }
52
+
53
+ /**
54
+ * Default path builder: users/{userId}/{collectionName}
55
+ */
56
+ const createDefaultPathBuilder =
57
+ (collectionName: string): PathBuilder =>
58
+ (userId: string) =>
59
+ ["users", userId, collectionName];
60
+
61
+ export class CreationsRepository
62
+ extends BaseRepository
63
+ implements ICreationsRepository
64
+ {
65
+ private readonly pathBuilder: PathBuilder;
66
+ private readonly documentMapper: DocumentMapper;
21
67
 
22
- export class CreationsRepository implements ICreationsRepository {
23
68
  constructor(
24
- private readonly db: Firestore | null,
25
69
  private readonly collectionName: string,
26
- ) {}
70
+ options?: RepositoryOptions,
71
+ ) {
72
+ super();
73
+ this.pathBuilder =
74
+ options?.pathBuilder ?? createDefaultPathBuilder(collectionName);
75
+ this.documentMapper = options?.documentMapper ?? mapDocumentToCreation;
76
+ }
27
77
 
28
78
  private getUserCollection(userId: string) {
29
- if (!this.db) return null;
30
- return collection(this.db, "users", userId, this.collectionName);
79
+ const db = this.getDb();
80
+ if (!db) return null;
81
+ const pathSegments = this.pathBuilder(userId);
82
+ return collection(db, pathSegments[0], ...pathSegments.slice(1));
83
+ }
84
+
85
+ private getDocRef(userId: string, creationId: string) {
86
+ const db = this.getDb();
87
+ if (!db) return null;
88
+ const pathSegments = this.pathBuilder(userId);
89
+ return doc(db, pathSegments[0], ...pathSegments.slice(1), creationId);
31
90
  }
32
91
 
33
92
  async getAll(userId: string): Promise<Creation[]> {
@@ -48,7 +107,7 @@ export class CreationsRepository implements ICreationsRepository {
48
107
 
49
108
  return snapshot.docs.map((docSnap) => {
50
109
  const data = docSnap.data() as CreationDocument;
51
- return mapDocumentToCreation(docSnap.id, data);
110
+ return this.documentMapper(docSnap.id, data);
52
111
  });
53
112
  } catch (error) {
54
113
  if (__DEV__) {
@@ -59,16 +118,10 @@ export class CreationsRepository implements ICreationsRepository {
59
118
  }
60
119
 
61
120
  async delete(userId: string, creationId: string): Promise<boolean> {
62
- if (!this.db) return false;
121
+ const docRef = this.getDocRef(userId, creationId);
122
+ if (!docRef) return false;
63
123
 
64
124
  try {
65
- const docRef = doc(
66
- this.db,
67
- "users",
68
- userId,
69
- this.collectionName,
70
- creationId,
71
- );
72
125
  await deleteDoc(docRef);
73
126
  return true;
74
127
  } catch {
@@ -81,16 +134,10 @@ export class CreationsRepository implements ICreationsRepository {
81
134
  creationId: string,
82
135
  isShared: boolean,
83
136
  ): Promise<boolean> {
84
- if (!this.db) return false;
137
+ const docRef = this.getDocRef(userId, creationId);
138
+ if (!docRef) return false;
85
139
 
86
140
  try {
87
- const docRef = doc(
88
- this.db,
89
- "users",
90
- userId,
91
- this.collectionName,
92
- creationId,
93
- );
94
141
  await updateDoc(docRef, { isShared });
95
142
  return true;
96
143
  } catch {
@@ -2,4 +2,7 @@
2
2
  * Infrastructure Repositories
3
3
  */
4
4
 
5
- export { CreationsRepository } from "./CreationsRepository";
5
+ export {
6
+ CreationsRepository,
7
+ type RepositoryOptions,
8
+ } from "./CreationsRepository";
package/src/types.d.ts CHANGED
@@ -2,6 +2,41 @@
2
2
  * Type declarations for external modules
3
3
  */
4
4
 
5
+ declare module "@umituz/react-native-firestore" {
6
+ import type { Firestore } from "firebase/firestore";
7
+
8
+ export class BaseRepository {
9
+ protected getDb(): Firestore | null;
10
+ protected getDbOrThrow(): Firestore;
11
+ protected isDbInitialized(): boolean;
12
+ protected isQuotaError(error: unknown): boolean;
13
+ protected handleQuotaError(error: unknown): never;
14
+ protected executeWithQuotaHandling<T>(
15
+ operation: () => Promise<T>,
16
+ ): Promise<T>;
17
+ protected trackRead(
18
+ collection: string,
19
+ count: number,
20
+ cached: boolean,
21
+ ): void;
22
+ protected trackWrite(
23
+ collection: string,
24
+ docId: string,
25
+ count: number,
26
+ ): void;
27
+ protected trackDelete(
28
+ collection: string,
29
+ docId: string,
30
+ count: number,
31
+ ): void;
32
+ destroy(): void;
33
+ }
34
+
35
+ export function getFirestore(): Firestore | null;
36
+ export function initializeFirestore(app: unknown): void;
37
+ export function isFirestoreInitialized(): boolean;
38
+ }
39
+
5
40
  declare module "@umituz/react-native-design-system" {
6
41
  import type { FC, ReactNode } from "react";
7
42
  import type { StyleProp, ViewStyle, TextStyle } from "react-native";