@umituz/react-native-ai-generation-content 1.17.166 → 1.17.168

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.17.166",
3
+ "version": "1.17.168",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -10,6 +10,8 @@ import { useAuth } from "@umituz/react-native-auth";
10
10
  import { createCreationsRepository } from "../../infrastructure/adapters";
11
11
  import type { Creation } from "../../domain/entities/Creation";
12
12
 
13
+ declare const __DEV__: boolean;
14
+
13
15
  /**
14
16
  * Configuration for creation persistence
15
17
  */
@@ -70,13 +72,24 @@ export function useCreationPersistence(
70
72
 
71
73
  const onProcessingStart = useCallback(
72
74
  <T extends BaseProcessingStartData>(data: T) => {
73
- if (!userId) return;
75
+ if (__DEV__) {
76
+ console.log("[useCreationPersistence] onProcessingStart called", { type, userId, data });
77
+ }
78
+
79
+ if (!userId) {
80
+ if (__DEV__) console.log("[useCreationPersistence] No userId, skipping");
81
+ return;
82
+ }
74
83
 
75
84
  const { creationId, ...rest } = data;
76
85
  const cleanMetadata = Object.fromEntries(
77
86
  Object.entries(rest).filter(([, v]) => v !== undefined && v !== null),
78
87
  );
79
88
 
89
+ if (__DEV__) {
90
+ console.log("[useCreationPersistence] cleanMetadata", cleanMetadata);
91
+ }
92
+
80
93
  const creation: Creation = {
81
94
  id: creationId,
82
95
  uri: "",
@@ -88,6 +101,10 @@ export function useCreationPersistence(
88
101
  metadata: cleanMetadata,
89
102
  };
90
103
 
104
+ if (__DEV__) {
105
+ console.log("[useCreationPersistence] Creating document", { creationId, type });
106
+ }
107
+
91
108
  repository.create(userId, creation);
92
109
  queryClient.invalidateQueries({ queryKey: ["creations"] });
93
110
  },
@@ -96,7 +113,18 @@ export function useCreationPersistence(
96
113
 
97
114
  const onProcessingComplete = useCallback(
98
115
  <T extends BaseProcessingResult>(result: T) => {
99
- if (!userId || !result.creationId) return;
116
+ if (__DEV__) {
117
+ console.log("[useCreationPersistence] onProcessingComplete called", {
118
+ creationId: result.creationId,
119
+ hasImageUrl: !!result.imageUrl,
120
+ hasVideoUrl: !!result.videoUrl,
121
+ });
122
+ }
123
+
124
+ if (!userId || !result.creationId) {
125
+ if (__DEV__) console.log("[useCreationPersistence] Missing userId or creationId, skipping");
126
+ return;
127
+ }
100
128
 
101
129
  const uri = result.imageUrl || result.videoUrl || "";
102
130
  const output = result.imageUrl
@@ -105,6 +133,13 @@ export function useCreationPersistence(
105
133
  ? { videoUrl: result.videoUrl }
106
134
  : undefined;
107
135
 
136
+ if (__DEV__) {
137
+ console.log("[useCreationPersistence] Updating document to completed", {
138
+ creationId: result.creationId,
139
+ uri: uri.substring(0, 50) + "...",
140
+ });
141
+ }
142
+
108
143
  repository.update(userId, result.creationId, {
109
144
  uri,
110
145
  status: "completed",
@@ -117,7 +152,18 @@ export function useCreationPersistence(
117
152
 
118
153
  const onError = useCallback(
119
154
  (error: string, creationId?: string) => {
120
- if (!userId || !creationId) return;
155
+ if (__DEV__) {
156
+ console.log("[useCreationPersistence] onError called", { error, creationId });
157
+ }
158
+
159
+ if (!userId || !creationId) {
160
+ if (__DEV__) console.log("[useCreationPersistence] Missing userId or creationId, skipping");
161
+ return;
162
+ }
163
+
164
+ if (__DEV__) {
165
+ console.log("[useCreationPersistence] Updating document to failed", { creationId });
166
+ }
121
167
 
122
168
  repository.update(userId, creationId, {
123
169
  status: "failed",
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Image Prompt Segments
3
+ * Reusable building blocks for composing AI image generation prompts
4
+ */
5
+
6
+ // =============================================================================
7
+ // IDENTITY PRESERVATION
8
+ // =============================================================================
9
+
10
+ export const IDENTITY_SEGMENTS = {
11
+ samePerson: "same person",
12
+ preserveIdentity: "preserve identity",
13
+ preserveGender: "preserve original gender",
14
+ preserveFace: "preserve original face structure",
15
+ preserveHair: "preserve original hair color and style",
16
+ preserveEyes: "preserve original eye color",
17
+ sameFeatures: "same facial features",
18
+ maintainLikeness: "maintain likeness",
19
+ } as const;
20
+
21
+ export const IDENTITY_NEGATIVE_SEGMENTS = {
22
+ genderSwap: "gender swap",
23
+ differentPerson: "different person",
24
+ wrongGender: "wrong gender",
25
+ changedIdentity: "changed identity",
26
+ } as const;
27
+
28
+ // =============================================================================
29
+ // ANIME STYLE
30
+ // =============================================================================
31
+
32
+ export const ANIME_STYLE_SEGMENTS = {
33
+ base: "2D anime illustration",
34
+ japaneseStyle: "japanese anime art style",
35
+ celShaded: "cel-shaded anime character",
36
+ animeEyes: "large sparkling anime eyes with detailed iris",
37
+ animeSkin: "smooth cel-shaded skin with subtle anime blush",
38
+ animeHair: "stylized anime hair with highlights",
39
+ ghibli: "Studio Ghibli inspired",
40
+ vibrantColors: "vibrant anime colors",
41
+ cleanLineart: "clean anime lineart",
42
+ professionalPortrait: "professional anime portrait",
43
+ } as const;
44
+
45
+ // =============================================================================
46
+ // QUALITY
47
+ // =============================================================================
48
+
49
+ export const QUALITY_SEGMENTS = {
50
+ highQuality: "high quality",
51
+ detailed: "highly detailed",
52
+ sharp: "sharp focus",
53
+ professional: "professional",
54
+ masterpiece: "masterpiece",
55
+ bestQuality: "best quality",
56
+ } as const;
57
+
58
+ export const QUALITY_NEGATIVE_SEGMENTS = {
59
+ lowQuality: "low quality",
60
+ blurry: "blurry",
61
+ pixelated: "pixelated",
62
+ artifacts: "jpeg artifacts",
63
+ watermark: "watermark",
64
+ signature: "signature",
65
+ } as const;
66
+
67
+ // =============================================================================
68
+ // REALISM AVOIDANCE (for stylized outputs)
69
+ // =============================================================================
70
+
71
+ export const ANTI_REALISM_SEGMENTS = {
72
+ photorealistic: "photorealistic",
73
+ realisticPhoto: "realistic photo",
74
+ render3D: "3D render",
75
+ hyperrealistic: "hyperrealistic",
76
+ realPerson: "real person",
77
+ naturalSkin: "natural skin texture",
78
+ pores: "pores",
79
+ wrinkles: "wrinkles",
80
+ } as const;
81
+
82
+ // =============================================================================
83
+ // ANATOMY NEGATIVE
84
+ // =============================================================================
85
+
86
+ export const ANATOMY_NEGATIVE_SEGMENTS = {
87
+ deformedFace: "deformed face",
88
+ badAnatomy: "bad anatomy",
89
+ extraLimbs: "extra limbs",
90
+ mutatedHands: "mutated hands",
91
+ extraFingers: "extra fingers",
92
+ missingFingers: "missing fingers",
93
+ } as const;
94
+
95
+ // =============================================================================
96
+ // PRESET COLLECTIONS
97
+ // =============================================================================
98
+
99
+ export const PRESET_COLLECTIONS = {
100
+ fullIdentityPreservation: Object.values(IDENTITY_SEGMENTS),
101
+ basicIdentityPreservation: [
102
+ IDENTITY_SEGMENTS.samePerson,
103
+ IDENTITY_SEGMENTS.preserveGender,
104
+ IDENTITY_SEGMENTS.preserveFace,
105
+ ],
106
+ animeStyle: Object.values(ANIME_STYLE_SEGMENTS),
107
+ highQuality: Object.values(QUALITY_SEGMENTS),
108
+ antiRealism: Object.values(ANTI_REALISM_SEGMENTS),
109
+ anatomyNegative: Object.values(ANATOMY_NEGATIVE_SEGMENTS),
110
+ identityNegative: Object.values(IDENTITY_NEGATIVE_SEGMENTS),
111
+ } as const;
112
+
113
+ // =============================================================================
114
+ // TYPES
115
+ // =============================================================================
116
+
117
+ export type IdentitySegment = keyof typeof IDENTITY_SEGMENTS;
118
+ export type AnimeStyleSegment = keyof typeof ANIME_STYLE_SEGMENTS;
119
+ export type QualitySegment = keyof typeof QUALITY_SEGMENTS;
@@ -320,4 +320,36 @@ export type {
320
320
  UsePromptGenerationActions,
321
321
  } from './presentation/hooks/usePromptGeneration';
322
322
 
323
- export { usePromptGeneration } from './presentation/hooks/usePromptGeneration';
323
+ export { usePromptGeneration } from './presentation/hooks/usePromptGeneration';
324
+
325
+ // =============================================================================
326
+ // IMAGE PROMPT BUILDING
327
+ // =============================================================================
328
+
329
+ export {
330
+ IDENTITY_SEGMENTS,
331
+ IDENTITY_NEGATIVE_SEGMENTS,
332
+ ANIME_STYLE_SEGMENTS,
333
+ QUALITY_SEGMENTS,
334
+ QUALITY_NEGATIVE_SEGMENTS,
335
+ ANTI_REALISM_SEGMENTS,
336
+ ANATOMY_NEGATIVE_SEGMENTS,
337
+ PRESET_COLLECTIONS,
338
+ } from './domain/entities/image-prompt-segments';
339
+
340
+ export type {
341
+ IdentitySegment,
342
+ AnimeStyleSegment,
343
+ QualitySegment,
344
+ } from './domain/entities/image-prompt-segments';
345
+
346
+ export {
347
+ ImagePromptBuilder,
348
+ createAnimeSelfiePrompt,
349
+ createStyleTransferPrompt,
350
+ } from './infrastructure/services/ImagePromptBuilder';
351
+
352
+ export type {
353
+ ImagePromptResult,
354
+ ImagePromptBuilderOptions,
355
+ } from './infrastructure/services/ImagePromptBuilder';
@@ -0,0 +1,200 @@
1
+ /**
2
+ * ImagePromptBuilder
3
+ * Fluent builder for composing AI image generation prompts
4
+ *
5
+ * @example
6
+ * const { prompt, negativePrompt } = ImagePromptBuilder.create()
7
+ * .withIdentityPreservation()
8
+ * .withAnimeStyle()
9
+ * .withQuality()
10
+ * .build();
11
+ */
12
+
13
+ import {
14
+ IDENTITY_NEGATIVE_SEGMENTS,
15
+ ANIME_STYLE_SEGMENTS,
16
+ QUALITY_SEGMENTS,
17
+ QUALITY_NEGATIVE_SEGMENTS,
18
+ ANTI_REALISM_SEGMENTS,
19
+ ANATOMY_NEGATIVE_SEGMENTS,
20
+ PRESET_COLLECTIONS,
21
+ } from "../../domain/entities/image-prompt-segments";
22
+
23
+ export interface ImagePromptResult {
24
+ prompt: string;
25
+ negativePrompt: string;
26
+ }
27
+
28
+ export interface ImagePromptBuilderOptions {
29
+ separator?: string;
30
+ }
31
+
32
+ export class ImagePromptBuilder {
33
+ private positiveSegments: string[] = [];
34
+ private negativeSegments: string[] = [];
35
+ private readonly separator: string;
36
+
37
+ private constructor(options?: ImagePromptBuilderOptions) {
38
+ this.separator = options?.separator ?? ", ";
39
+ }
40
+
41
+ /**
42
+ * Create a new ImagePromptBuilder instance
43
+ */
44
+ static create(options?: ImagePromptBuilderOptions): ImagePromptBuilder {
45
+ return new ImagePromptBuilder(options);
46
+ }
47
+
48
+ /**
49
+ * Add identity preservation prompts
50
+ * Ensures the AI preserves the original person's features
51
+ */
52
+ withIdentityPreservation(full = true): this {
53
+ const segments = full
54
+ ? PRESET_COLLECTIONS.fullIdentityPreservation
55
+ : PRESET_COLLECTIONS.basicIdentityPreservation;
56
+
57
+ this.positiveSegments.push(...segments);
58
+ this.negativeSegments.push(...Object.values(IDENTITY_NEGATIVE_SEGMENTS));
59
+ return this;
60
+ }
61
+
62
+ /**
63
+ * Add anime style prompts
64
+ */
65
+ withAnimeStyle(): this {
66
+ this.positiveSegments.push(...Object.values(ANIME_STYLE_SEGMENTS));
67
+ this.negativeSegments.push(...Object.values(ANTI_REALISM_SEGMENTS));
68
+ return this;
69
+ }
70
+
71
+ /**
72
+ * Add quality enhancement prompts
73
+ */
74
+ withQuality(): this {
75
+ this.positiveSegments.push(...Object.values(QUALITY_SEGMENTS));
76
+ this.negativeSegments.push(...Object.values(QUALITY_NEGATIVE_SEGMENTS));
77
+ return this;
78
+ }
79
+
80
+ /**
81
+ * Add anatomy safety negative prompts
82
+ */
83
+ withAnatomySafety(): this {
84
+ this.negativeSegments.push(...Object.values(ANATOMY_NEGATIVE_SEGMENTS));
85
+ return this;
86
+ }
87
+
88
+ /**
89
+ * Add anti-realism prompts (for stylized outputs)
90
+ */
91
+ withAntiRealism(): this {
92
+ this.negativeSegments.push(...Object.values(ANTI_REALISM_SEGMENTS));
93
+ return this;
94
+ }
95
+
96
+ /**
97
+ * Add custom positive segments
98
+ */
99
+ withSegments(segments: string[]): this {
100
+ this.positiveSegments.push(...segments);
101
+ return this;
102
+ }
103
+
104
+ /**
105
+ * Add custom negative segments
106
+ */
107
+ withNegativeSegments(segments: string[]): this {
108
+ this.negativeSegments.push(...segments);
109
+ return this;
110
+ }
111
+
112
+ /**
113
+ * Add a single custom segment
114
+ */
115
+ withSegment(segment: string): this {
116
+ this.positiveSegments.push(segment);
117
+ return this;
118
+ }
119
+
120
+ /**
121
+ * Add a single negative segment
122
+ */
123
+ withNegativeSegment(segment: string): this {
124
+ this.negativeSegments.push(segment);
125
+ return this;
126
+ }
127
+
128
+ /**
129
+ * Prepend segments (add to beginning)
130
+ */
131
+ prependSegments(segments: string[]): this {
132
+ this.positiveSegments.unshift(...segments);
133
+ return this;
134
+ }
135
+
136
+ /**
137
+ * Create a new builder extending this one
138
+ */
139
+ extend(): ImagePromptBuilder {
140
+ const builder = ImagePromptBuilder.create({ separator: this.separator });
141
+ builder.positiveSegments = [...this.positiveSegments];
142
+ builder.negativeSegments = [...this.negativeSegments];
143
+ return builder;
144
+ }
145
+
146
+ /**
147
+ * Build the final prompt strings
148
+ */
149
+ build(): ImagePromptResult {
150
+ // Remove duplicates and filter empty values
151
+ const uniquePositive = [...new Set(this.positiveSegments)].filter(Boolean);
152
+ const uniqueNegative = [...new Set(this.negativeSegments)].filter(Boolean);
153
+
154
+ return {
155
+ prompt: uniquePositive.join(this.separator),
156
+ negativePrompt: uniqueNegative.join(this.separator),
157
+ };
158
+ }
159
+
160
+ /**
161
+ * Get current positive segments (for debugging)
162
+ */
163
+ getPositiveSegments(): string[] {
164
+ return [...this.positiveSegments];
165
+ }
166
+
167
+ /**
168
+ * Get current negative segments (for debugging)
169
+ */
170
+ getNegativeSegments(): string[] {
171
+ return [...this.negativeSegments];
172
+ }
173
+ }
174
+
175
+ // =============================================================================
176
+ // PRESET BUILDERS
177
+ // =============================================================================
178
+
179
+ /**
180
+ * Create an anime selfie prompt builder with identity preservation
181
+ */
182
+ export function createAnimeSelfiePrompt(): ImagePromptResult {
183
+ return ImagePromptBuilder.create()
184
+ .withIdentityPreservation()
185
+ .withAnimeStyle()
186
+ .withAnatomySafety()
187
+ .build();
188
+ }
189
+
190
+ /**
191
+ * Create a style transfer prompt builder with identity preservation
192
+ */
193
+ export function createStyleTransferPrompt(style: string): ImagePromptResult {
194
+ return ImagePromptBuilder.create()
195
+ .withIdentityPreservation()
196
+ .withSegment(`${style} style`)
197
+ .withQuality()
198
+ .withAnatomySafety()
199
+ .build();
200
+ }