@umituz/react-native-google-stitch-sdk 1.0.2 → 1.0.3
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 +5 -1
- package/src/domain/entities/index.ts +13 -1
- package/src/domain/entities/stitch.entity.ts +78 -8
- package/src/domain/interfaces/stitch-service.interface.ts +53 -11
- package/src/domains/core/index.ts +11 -3
- package/src/index.ts +0 -1
- package/src/infrastructure/constants/index.ts +1 -1
- package/src/infrastructure/constants/stitch.constants.ts +1 -6
- package/src/infrastructure/services/stitch.service.ts +179 -37
- package/src/presentation/hooks/useStitch.ts +151 -29
- package/src/infrastructure/utils/index.ts +0 -6
- package/src/presentation/components/index.ts +0 -6
- package/src/presentation/stores/index.ts +0 -6
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-google-stitch-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "React Native wrapper for Google Labs Stitch SDK with TypeScript support",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "./src/index.ts",
|
|
6
7
|
"types": "./src/index.ts",
|
|
7
8
|
"sideEffects": false,
|
|
@@ -34,6 +35,9 @@
|
|
|
34
35
|
"publishConfig": {
|
|
35
36
|
"access": "public"
|
|
36
37
|
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@google/stitch-sdk": "^0.0.3"
|
|
40
|
+
},
|
|
37
41
|
"peerDependencies": {
|
|
38
42
|
"react": ">=18.2.0",
|
|
39
43
|
"react-native": ">=0.74.0"
|
|
@@ -3,4 +3,16 @@
|
|
|
3
3
|
* @description Core entity definitions for Stitch SDK
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
export type {
|
|
6
|
+
export type {
|
|
7
|
+
StitchProject,
|
|
8
|
+
StitchScreen,
|
|
9
|
+
DeviceType,
|
|
10
|
+
ModelId,
|
|
11
|
+
CreativeRange,
|
|
12
|
+
VariantAspect,
|
|
13
|
+
VariantOptions,
|
|
14
|
+
ScreenGenerateInput,
|
|
15
|
+
ScreenEditInput,
|
|
16
|
+
ScreenVariantsInput,
|
|
17
|
+
ScreenOutput,
|
|
18
|
+
} from './stitch.entity';
|
|
@@ -1,15 +1,85 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Stitch
|
|
3
|
-
* @description
|
|
2
|
+
* Stitch Entities
|
|
3
|
+
* @description Domain entities matching Google Labs Stitch SDK structure
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Device types for screen generation
|
|
8
|
+
*/
|
|
9
|
+
export type DeviceType = 'MOBILE' | 'DESKTOP' | 'TABLET' | 'AGNOSTIC';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Model IDs for generation
|
|
13
|
+
*/
|
|
14
|
+
export type ModelId = 'GEMINI_3_PRO' | 'GEMINI_3_FLASH';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Creative range for variants
|
|
18
|
+
*/
|
|
19
|
+
export type CreativeRange = 'REFINE' | 'EXPLORE' | 'REIMAGINE';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Variant aspects
|
|
23
|
+
*/
|
|
24
|
+
export type VariantAspect = 'LAYOUT' | 'COLOR_SCHEME' | 'IMAGES' | 'TEXT_FONT' | 'TEXT_CONTENT';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Represents a Stitch project containing screens
|
|
28
|
+
*/
|
|
6
29
|
export interface StitchProject {
|
|
7
30
|
readonly id: string;
|
|
8
|
-
readonly
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
31
|
+
readonly projectId: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Represents a generated UI screen
|
|
36
|
+
*/
|
|
37
|
+
export interface StitchScreen {
|
|
38
|
+
readonly id: string;
|
|
39
|
+
readonly screenId: string;
|
|
40
|
+
readonly projectId: string;
|
|
12
41
|
}
|
|
13
42
|
|
|
14
|
-
|
|
15
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Options for generating variants
|
|
45
|
+
*/
|
|
46
|
+
export interface VariantOptions {
|
|
47
|
+
readonly variantCount?: number;
|
|
48
|
+
readonly creativeRange?: CreativeRange;
|
|
49
|
+
readonly aspects?: VariantAspect[];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Input for screen generation
|
|
54
|
+
*/
|
|
55
|
+
export interface ScreenGenerateInput {
|
|
56
|
+
readonly prompt: string;
|
|
57
|
+
readonly deviceType?: DeviceType;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Input for screen editing
|
|
62
|
+
*/
|
|
63
|
+
export interface ScreenEditInput {
|
|
64
|
+
readonly prompt: string;
|
|
65
|
+
readonly deviceType?: DeviceType;
|
|
66
|
+
readonly modelId?: ModelId;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Input for variant generation
|
|
71
|
+
*/
|
|
72
|
+
export interface ScreenVariantsInput {
|
|
73
|
+
readonly prompt: string;
|
|
74
|
+
readonly options?: VariantOptions;
|
|
75
|
+
readonly deviceType?: DeviceType;
|
|
76
|
+
readonly modelId?: ModelId;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Screen output with URLs
|
|
81
|
+
*/
|
|
82
|
+
export interface ScreenOutput {
|
|
83
|
+
readonly htmlUrl: string;
|
|
84
|
+
readonly imageUrl: string;
|
|
85
|
+
}
|
|
@@ -3,31 +3,73 @@
|
|
|
3
3
|
* @description Contract for Stitch SDK service implementations
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type {
|
|
6
|
+
import type {
|
|
7
|
+
StitchProject,
|
|
8
|
+
StitchScreen,
|
|
9
|
+
ScreenGenerateInput,
|
|
10
|
+
ScreenEditInput,
|
|
11
|
+
ScreenVariantsInput,
|
|
12
|
+
ScreenOutput,
|
|
13
|
+
} from '../entities';
|
|
7
14
|
|
|
8
15
|
export interface IStitchService {
|
|
9
16
|
/**
|
|
10
|
-
*
|
|
17
|
+
* List all accessible projects
|
|
11
18
|
*/
|
|
12
|
-
|
|
19
|
+
listProjects(): Promise<StitchProject[]>;
|
|
13
20
|
|
|
14
21
|
/**
|
|
15
|
-
*
|
|
22
|
+
* Get a project reference by ID (no API call)
|
|
16
23
|
*/
|
|
17
|
-
|
|
24
|
+
getProject(projectId: string): StitchProject;
|
|
18
25
|
|
|
19
26
|
/**
|
|
20
|
-
*
|
|
27
|
+
* List all screens in a project
|
|
21
28
|
*/
|
|
22
|
-
|
|
29
|
+
listScreens(projectId: string): Promise<StitchScreen[]>;
|
|
23
30
|
|
|
24
31
|
/**
|
|
25
|
-
*
|
|
32
|
+
* Get a specific screen by ID
|
|
26
33
|
*/
|
|
27
|
-
|
|
34
|
+
getScreen(projectId: string, screenId: string): Promise<StitchScreen>;
|
|
28
35
|
|
|
29
36
|
/**
|
|
30
|
-
*
|
|
37
|
+
* Generate a screen from a text prompt
|
|
31
38
|
*/
|
|
32
|
-
|
|
39
|
+
generateScreen(projectId: string, input: ScreenGenerateInput): Promise<StitchScreen>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Edit a screen with a text prompt
|
|
43
|
+
*/
|
|
44
|
+
editScreen(projectId: string, screenId: string, input: ScreenEditInput): Promise<StitchScreen>;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Generate design variants of a screen
|
|
48
|
+
*/
|
|
49
|
+
generateVariants(projectId: string, screenId: string, input: ScreenVariantsInput): Promise<StitchScreen[]>;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get the screen's HTML download URL
|
|
53
|
+
*/
|
|
54
|
+
getScreenHtml(projectId: string, screenId: string): Promise<string>;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get the screen's screenshot download URL
|
|
58
|
+
*/
|
|
59
|
+
getScreenImage(projectId: string, screenId: string): Promise<string>;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Get both HTML and image URLs for a screen
|
|
63
|
+
*/
|
|
64
|
+
getScreenOutput(projectId: string, screenId: string): Promise<ScreenOutput>;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Create a new project using MCP tool
|
|
68
|
+
*/
|
|
69
|
+
createProject(title: string): Promise<{ projectId: string }>;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Call MCP tool directly
|
|
73
|
+
*/
|
|
74
|
+
callTool<T = unknown>(name: string, args: Record<string, unknown>): Promise<T>;
|
|
33
75
|
}
|
|
@@ -7,8 +7,16 @@
|
|
|
7
7
|
// Domain entities
|
|
8
8
|
export type {
|
|
9
9
|
StitchProject,
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
StitchScreen,
|
|
11
|
+
DeviceType,
|
|
12
|
+
ModelId,
|
|
13
|
+
CreativeRange,
|
|
14
|
+
VariantAspect,
|
|
15
|
+
VariantOptions,
|
|
16
|
+
ScreenGenerateInput,
|
|
17
|
+
ScreenEditInput,
|
|
18
|
+
ScreenVariantsInput,
|
|
19
|
+
ScreenOutput,
|
|
12
20
|
} from '../../domain/entities';
|
|
13
21
|
|
|
14
22
|
// Infrastructure services
|
|
@@ -20,4 +28,4 @@ export { useStitch } from '../../presentation/hooks';
|
|
|
20
28
|
export type { UseStitchConfig, UseStitchReturn } from '../../presentation/hooks';
|
|
21
29
|
|
|
22
30
|
// Constants
|
|
23
|
-
export {
|
|
31
|
+
export { STITCH_ERROR_MESSAGES } from '../../infrastructure/constants';
|
package/src/index.ts
CHANGED
|
@@ -3,13 +3,8 @@
|
|
|
3
3
|
* @description Configuration constants for Stitch SDK
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
export const STITCH_DEFAULT_CONFIG = {
|
|
7
|
-
API_TIMEOUT: 30000,
|
|
8
|
-
MAX_RETRIES: 3,
|
|
9
|
-
} as const;
|
|
10
|
-
|
|
11
6
|
export const STITCH_ERROR_MESSAGES = {
|
|
12
7
|
NOT_INITIALIZED: 'StitchService not initialized. Call initialize() first.',
|
|
13
8
|
INVALID_PROJECT_ID: 'Invalid project ID provided.',
|
|
14
|
-
NETWORK_ERROR: 'Network error occurred while communicating with Stitch SDK.',
|
|
15
9
|
} as const;
|
|
10
|
+
|
|
@@ -1,86 +1,228 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Stitch Service
|
|
3
3
|
* @description Main service implementation for Google Labs Stitch SDK wrapper
|
|
4
|
-
* @note This is a placeholder implementation. Replace with actual SDK calls when available.
|
|
5
4
|
*/
|
|
6
5
|
|
|
7
6
|
import type { IStitchService } from '../../domain/interfaces';
|
|
8
|
-
import type {
|
|
7
|
+
import type {
|
|
8
|
+
StitchProject,
|
|
9
|
+
StitchScreen,
|
|
10
|
+
DeviceType,
|
|
11
|
+
ModelId,
|
|
12
|
+
ScreenGenerateInput,
|
|
13
|
+
ScreenEditInput,
|
|
14
|
+
ScreenVariantsInput,
|
|
15
|
+
ScreenOutput,
|
|
16
|
+
} from '../../domain/entities';
|
|
17
|
+
import { STITCH_ERROR_MESSAGES } from '../constants';
|
|
18
|
+
import { stitch, type Project as SDKProject } from '@google/stitch-sdk';
|
|
9
19
|
|
|
10
20
|
export interface StitchServiceConfig {
|
|
11
21
|
apiKey?: string;
|
|
12
22
|
baseUrl?: string;
|
|
13
23
|
}
|
|
14
24
|
|
|
25
|
+
type DeviceTypeSDK = 'MOBILE' | 'DESKTOP' | 'TABLET' | 'AGNOSTIC';
|
|
26
|
+
type ModelIdSDK = 'GEMINI_3_PRO' | 'GEMINI_3_FLASH';
|
|
27
|
+
|
|
28
|
+
const DEVICE_TYPES_SDK: Record<DeviceType, DeviceTypeSDK> = {
|
|
29
|
+
MOBILE: 'MOBILE',
|
|
30
|
+
DESKTOP: 'DESKTOP',
|
|
31
|
+
TABLET: 'TABLET',
|
|
32
|
+
AGNOSTIC: 'AGNOSTIC',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const MODEL_IDS_SDK: Record<ModelId, ModelIdSDK> = {
|
|
36
|
+
GEMINI_3_PRO: 'GEMINI_3_PRO',
|
|
37
|
+
GEMINI_3_FLASH: 'GEMINI_3_FLASH',
|
|
38
|
+
};
|
|
39
|
+
|
|
15
40
|
class StitchService implements IStitchService {
|
|
16
41
|
private config: StitchServiceConfig | null = null;
|
|
17
42
|
|
|
18
43
|
initialize(config: StitchServiceConfig): void {
|
|
19
44
|
this.config = config;
|
|
45
|
+
// SDK uses environment variable STITCH_API_KEY by default
|
|
20
46
|
}
|
|
21
47
|
|
|
22
48
|
isInitialized(): boolean {
|
|
23
49
|
return this.config !== null;
|
|
24
50
|
}
|
|
25
51
|
|
|
26
|
-
|
|
52
|
+
private ensureInitialized(): void {
|
|
53
|
+
if (!this.isInitialized()) {
|
|
54
|
+
throw new Error(STITCH_ERROR_MESSAGES.NOT_INITIALIZED);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private validateProjectId(projectId: string): void {
|
|
59
|
+
if (!projectId || projectId.trim().length === 0) {
|
|
60
|
+
throw new Error(STITCH_ERROR_MESSAGES.INVALID_PROJECT_ID);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private validateScreenId(screenId: string): void {
|
|
65
|
+
if (!screenId || screenId.trim().length === 0) {
|
|
66
|
+
throw new Error('Invalid screen ID provided.');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async listProjects(): Promise<StitchProject[]> {
|
|
27
71
|
this.ensureInitialized();
|
|
72
|
+
const projects = await stitch.projects();
|
|
73
|
+
|
|
74
|
+
return projects.map(
|
|
75
|
+
(p: { id: string; projectId: string }): StitchProject => ({
|
|
76
|
+
id: p.id,
|
|
77
|
+
projectId: p.projectId,
|
|
78
|
+
})
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
getProject(projectId: string): StitchProject {
|
|
83
|
+
this.ensureInitialized();
|
|
84
|
+
this.validateProjectId(projectId);
|
|
85
|
+
|
|
86
|
+
const project = stitch.project(projectId);
|
|
28
87
|
|
|
29
|
-
// TODO: Replace with actual SDK call
|
|
30
|
-
// Example: const response = await fetch(`${this.config.baseUrl}/projects/${projectId}`);
|
|
31
88
|
return {
|
|
32
|
-
id:
|
|
33
|
-
|
|
34
|
-
description: 'Placeholder project',
|
|
35
|
-
createdAt: new Date(),
|
|
36
|
-
updatedAt: new Date(),
|
|
89
|
+
id: project.id,
|
|
90
|
+
projectId: project.projectId,
|
|
37
91
|
};
|
|
38
92
|
}
|
|
39
93
|
|
|
40
|
-
async
|
|
41
|
-
this.
|
|
94
|
+
private async getSDKProject(projectId: string): Promise<SDKProject> {
|
|
95
|
+
this.validateProjectId(projectId);
|
|
96
|
+
|
|
97
|
+
const project = stitch.project(projectId);
|
|
98
|
+
|
|
99
|
+
// Force a call to validate the project exists
|
|
100
|
+
await project.screens();
|
|
42
101
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
102
|
+
return project;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async listScreens(projectId: string): Promise<StitchScreen[]> {
|
|
106
|
+
const project = await this.getSDKProject(projectId);
|
|
107
|
+
const screens = await project.screens();
|
|
108
|
+
|
|
109
|
+
return screens.map(
|
|
110
|
+
(s: { id: string; screenId: string; projectId: string }): StitchScreen => ({
|
|
111
|
+
id: s.id,
|
|
112
|
+
screenId: s.screenId,
|
|
113
|
+
projectId: s.projectId,
|
|
114
|
+
})
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async getScreen(projectId: string, screenId: string): Promise<StitchScreen> {
|
|
119
|
+
this.validateScreenId(screenId);
|
|
120
|
+
|
|
121
|
+
const project = await this.getSDKProject(projectId);
|
|
122
|
+
const screen = await project.getScreen(screenId);
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
id: screen.id,
|
|
126
|
+
screenId: screen.screenId,
|
|
127
|
+
projectId: screen.projectId,
|
|
49
128
|
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async generateScreen(projectId: string, input: ScreenGenerateInput): Promise<StitchScreen> {
|
|
132
|
+
const project = await this.getSDKProject(projectId);
|
|
50
133
|
|
|
51
|
-
|
|
134
|
+
const deviceTypeSDK = input.deviceType ? DEVICE_TYPES_SDK[input.deviceType] : undefined;
|
|
135
|
+
const screen = await project.generate(input.prompt, deviceTypeSDK);
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
id: screen.id,
|
|
139
|
+
screenId: screen.screenId,
|
|
140
|
+
projectId: screen.projectId,
|
|
141
|
+
};
|
|
52
142
|
}
|
|
53
143
|
|
|
54
|
-
async
|
|
55
|
-
|
|
144
|
+
async editScreen(
|
|
145
|
+
_projectId: string,
|
|
146
|
+
screenId: string,
|
|
147
|
+
input: ScreenEditInput
|
|
148
|
+
): Promise<StitchScreen> {
|
|
149
|
+
this.validateScreenId(screenId);
|
|
150
|
+
|
|
151
|
+
const project = stitch.project(_projectId);
|
|
152
|
+
const screen = await project.getScreen(screenId);
|
|
153
|
+
|
|
154
|
+
const deviceTypeSDK = input.deviceType ? DEVICE_TYPES_SDK[input.deviceType] : undefined;
|
|
155
|
+
const modelIdSDK = input.modelId ? MODEL_IDS_SDK[input.modelId] : undefined;
|
|
156
|
+
const edited = await screen.edit(input.prompt, deviceTypeSDK, modelIdSDK);
|
|
56
157
|
|
|
57
|
-
// TODO: Replace with actual SDK call
|
|
58
|
-
const existing = await this.readProject(projectId);
|
|
59
158
|
return {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
159
|
+
id: edited.id,
|
|
160
|
+
screenId: edited.screenId,
|
|
161
|
+
projectId: edited.projectId,
|
|
63
162
|
};
|
|
64
163
|
}
|
|
65
164
|
|
|
66
|
-
async
|
|
67
|
-
|
|
165
|
+
async generateVariants(
|
|
166
|
+
_projectId: string,
|
|
167
|
+
screenId: string,
|
|
168
|
+
input: ScreenVariantsInput
|
|
169
|
+
): Promise<StitchScreen[]> {
|
|
170
|
+
this.validateScreenId(screenId);
|
|
171
|
+
|
|
172
|
+
const project = stitch.project(_projectId);
|
|
173
|
+
const screen = await project.getScreen(screenId);
|
|
174
|
+
|
|
175
|
+
const deviceTypeSDK = input.deviceType ? DEVICE_TYPES_SDK[input.deviceType] : undefined;
|
|
176
|
+
const modelIdSDK = input.modelId ? MODEL_IDS_SDK[input.modelId] : undefined;
|
|
68
177
|
|
|
69
|
-
|
|
70
|
-
|
|
178
|
+
const variants = await screen.variants(input.prompt, input.options, deviceTypeSDK, modelIdSDK);
|
|
179
|
+
|
|
180
|
+
return variants.map(
|
|
181
|
+
(v: { id: string; screenId: string; projectId: string }): StitchScreen => ({
|
|
182
|
+
id: v.id,
|
|
183
|
+
screenId: v.screenId,
|
|
184
|
+
projectId: v.projectId,
|
|
185
|
+
})
|
|
186
|
+
);
|
|
71
187
|
}
|
|
72
188
|
|
|
73
|
-
async
|
|
189
|
+
async getScreenHtml(_projectId: string, screenId: string): Promise<string> {
|
|
190
|
+
this.validateScreenId(screenId);
|
|
191
|
+
|
|
192
|
+
const project = stitch.project(_projectId);
|
|
193
|
+
const screen = await project.getScreen(screenId);
|
|
194
|
+
|
|
195
|
+
return await screen.getHtml();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async getScreenImage(_projectId: string, screenId: string): Promise<string> {
|
|
199
|
+
this.validateScreenId(screenId);
|
|
200
|
+
|
|
201
|
+
const project = stitch.project(_projectId);
|
|
202
|
+
const screen = await project.getScreen(screenId);
|
|
203
|
+
|
|
204
|
+
return await screen.getImage();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async getScreenOutput(projectId: string, screenId: string): Promise<ScreenOutput> {
|
|
208
|
+
const [htmlUrl, imageUrl] = await Promise.all([
|
|
209
|
+
this.getScreenHtml(projectId, screenId),
|
|
210
|
+
this.getScreenImage(projectId, screenId),
|
|
211
|
+
]);
|
|
212
|
+
|
|
213
|
+
return { htmlUrl, imageUrl };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
async createProject(title: string): Promise<{ projectId: string }> {
|
|
74
217
|
this.ensureInitialized();
|
|
218
|
+
const result = await stitch.callTool<{ projectId: string }>('create_project', { title });
|
|
75
219
|
|
|
76
|
-
|
|
77
|
-
return [];
|
|
220
|
+
return result;
|
|
78
221
|
}
|
|
79
222
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
223
|
+
async callTool<T = unknown>(name: string, args: Record<string, unknown>): Promise<T> {
|
|
224
|
+
this.ensureInitialized();
|
|
225
|
+
return await stitch.callTool<T>(name, args);
|
|
84
226
|
}
|
|
85
227
|
}
|
|
86
228
|
|
|
@@ -4,7 +4,14 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { useCallback, useEffect, useState } from 'react';
|
|
7
|
-
import type {
|
|
7
|
+
import type {
|
|
8
|
+
StitchProject,
|
|
9
|
+
StitchScreen,
|
|
10
|
+
ScreenGenerateInput,
|
|
11
|
+
ScreenEditInput,
|
|
12
|
+
ScreenVariantsInput,
|
|
13
|
+
ScreenOutput,
|
|
14
|
+
} from '../../domain/entities';
|
|
8
15
|
import { stitchService } from '../../infrastructure/services';
|
|
9
16
|
|
|
10
17
|
export interface UseStitchConfig {
|
|
@@ -16,11 +23,18 @@ export interface UseStitchConfig {
|
|
|
16
23
|
export interface UseStitchReturn {
|
|
17
24
|
isLoading: boolean;
|
|
18
25
|
error: Error | null;
|
|
19
|
-
readProject: (_projectId: string) => Promise<StitchProject>;
|
|
20
|
-
writeProject: (_input: StitchProjectCreateInput) => Promise<StitchProject>;
|
|
21
|
-
updateProject: (_projectId: string, _input: StitchProjectUpdateInput) => Promise<StitchProject>;
|
|
22
|
-
deleteProject: (_projectId: string) => Promise<void>;
|
|
23
26
|
listProjects: () => Promise<StitchProject[]>;
|
|
27
|
+
getProject: (projectId: string) => StitchProject;
|
|
28
|
+
listScreens: (projectId: string) => Promise<StitchScreen[]>;
|
|
29
|
+
getScreen: (projectId: string, screenId: string) => Promise<StitchScreen>;
|
|
30
|
+
generateScreen: (projectId: string, input: ScreenGenerateInput) => Promise<StitchScreen>;
|
|
31
|
+
editScreen: (projectId: string, screenId: string, input: ScreenEditInput) => Promise<StitchScreen>;
|
|
32
|
+
generateVariants: (projectId: string, screenId: string, input: ScreenVariantsInput) => Promise<StitchScreen[]>;
|
|
33
|
+
getScreenHtml: (projectId: string, screenId: string) => Promise<string>;
|
|
34
|
+
getScreenImage: (projectId: string, screenId: string) => Promise<string>;
|
|
35
|
+
getScreenOutput: (projectId: string, screenId: string) => Promise<ScreenOutput>;
|
|
36
|
+
createProject: (title: string) => Promise<{ projectId: string }>;
|
|
37
|
+
callTool: <T = unknown>(name: string, args: Record<string, unknown>) => Promise<T>;
|
|
24
38
|
}
|
|
25
39
|
|
|
26
40
|
export function useStitch(config?: UseStitchConfig): UseStitchReturn {
|
|
@@ -31,16 +45,16 @@ export function useStitch(config?: UseStitchConfig): UseStitchReturn {
|
|
|
31
45
|
if (config?.autoInitialize && config.apiKey) {
|
|
32
46
|
stitchService.initialize({ apiKey: config.apiKey, baseUrl: config.baseUrl });
|
|
33
47
|
}
|
|
34
|
-
}, [config]);
|
|
48
|
+
}, [config?.apiKey, config?.baseUrl, config?.autoInitialize]);
|
|
35
49
|
|
|
36
|
-
const
|
|
50
|
+
const listProjects = useCallback(async () => {
|
|
37
51
|
setIsLoading(true);
|
|
38
52
|
setError(null);
|
|
39
53
|
try {
|
|
40
|
-
const
|
|
41
|
-
return
|
|
54
|
+
const projects = await stitchService.listProjects();
|
|
55
|
+
return projects;
|
|
42
56
|
} catch (err) {
|
|
43
|
-
const error = err instanceof Error ? err : new Error('Failed to
|
|
57
|
+
const error = err instanceof Error ? err : new Error('Failed to list projects');
|
|
44
58
|
setError(error);
|
|
45
59
|
throw error;
|
|
46
60
|
} finally {
|
|
@@ -48,14 +62,18 @@ export function useStitch(config?: UseStitchConfig): UseStitchReturn {
|
|
|
48
62
|
}
|
|
49
63
|
}, []);
|
|
50
64
|
|
|
51
|
-
const
|
|
65
|
+
const getProject = useCallback((projectId: string) => {
|
|
66
|
+
return stitchService.getProject(projectId);
|
|
67
|
+
}, []);
|
|
68
|
+
|
|
69
|
+
const listScreens = useCallback(async (projectId: string) => {
|
|
52
70
|
setIsLoading(true);
|
|
53
71
|
setError(null);
|
|
54
72
|
try {
|
|
55
|
-
const
|
|
56
|
-
return
|
|
73
|
+
const screens = await stitchService.listScreens(projectId);
|
|
74
|
+
return screens;
|
|
57
75
|
} catch (err) {
|
|
58
|
-
const error = err instanceof Error ? err : new Error('Failed to
|
|
76
|
+
const error = err instanceof Error ? err : new Error('Failed to list screens');
|
|
59
77
|
setError(error);
|
|
60
78
|
throw error;
|
|
61
79
|
} finally {
|
|
@@ -63,14 +81,14 @@ export function useStitch(config?: UseStitchConfig): UseStitchReturn {
|
|
|
63
81
|
}
|
|
64
82
|
}, []);
|
|
65
83
|
|
|
66
|
-
const
|
|
84
|
+
const getScreen = useCallback(async (projectId: string, screenId: string) => {
|
|
67
85
|
setIsLoading(true);
|
|
68
86
|
setError(null);
|
|
69
87
|
try {
|
|
70
|
-
const
|
|
71
|
-
return
|
|
88
|
+
const screen = await stitchService.getScreen(projectId, screenId);
|
|
89
|
+
return screen;
|
|
72
90
|
} catch (err) {
|
|
73
|
-
const error = err instanceof Error ? err : new Error('Failed to
|
|
91
|
+
const error = err instanceof Error ? err : new Error('Failed to get screen');
|
|
74
92
|
setError(error);
|
|
75
93
|
throw error;
|
|
76
94
|
} finally {
|
|
@@ -78,13 +96,14 @@ export function useStitch(config?: UseStitchConfig): UseStitchReturn {
|
|
|
78
96
|
}
|
|
79
97
|
}, []);
|
|
80
98
|
|
|
81
|
-
const
|
|
99
|
+
const generateScreen = useCallback(async (projectId: string, input: ScreenGenerateInput) => {
|
|
82
100
|
setIsLoading(true);
|
|
83
101
|
setError(null);
|
|
84
102
|
try {
|
|
85
|
-
await stitchService.
|
|
103
|
+
const screen = await stitchService.generateScreen(projectId, input);
|
|
104
|
+
return screen;
|
|
86
105
|
} catch (err) {
|
|
87
|
-
const error = err instanceof Error ? err : new Error('Failed to
|
|
106
|
+
const error = err instanceof Error ? err : new Error('Failed to generate screen');
|
|
88
107
|
setError(error);
|
|
89
108
|
throw error;
|
|
90
109
|
} finally {
|
|
@@ -92,14 +111,110 @@ export function useStitch(config?: UseStitchConfig): UseStitchReturn {
|
|
|
92
111
|
}
|
|
93
112
|
}, []);
|
|
94
113
|
|
|
95
|
-
const
|
|
114
|
+
const editScreen = useCallback(
|
|
115
|
+
async (projectId: string, screenId: string, input: ScreenEditInput) => {
|
|
116
|
+
setIsLoading(true);
|
|
117
|
+
setError(null);
|
|
118
|
+
try {
|
|
119
|
+
const screen = await stitchService.editScreen(projectId, screenId, input);
|
|
120
|
+
return screen;
|
|
121
|
+
} catch (err) {
|
|
122
|
+
const error = err instanceof Error ? err : new Error('Failed to edit screen');
|
|
123
|
+
setError(error);
|
|
124
|
+
throw error;
|
|
125
|
+
} finally {
|
|
126
|
+
setIsLoading(false);
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
[]
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
const generateVariants = useCallback(
|
|
133
|
+
async (projectId: string, screenId: string, input: ScreenVariantsInput) => {
|
|
134
|
+
setIsLoading(true);
|
|
135
|
+
setError(null);
|
|
136
|
+
try {
|
|
137
|
+
const variants = await stitchService.generateVariants(projectId, screenId, input);
|
|
138
|
+
return variants;
|
|
139
|
+
} catch (err) {
|
|
140
|
+
const error = err instanceof Error ? err : new Error('Failed to generate variants');
|
|
141
|
+
setError(error);
|
|
142
|
+
throw error;
|
|
143
|
+
} finally {
|
|
144
|
+
setIsLoading(false);
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
[]
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
const getScreenHtml = useCallback(async (projectId: string, screenId: string) => {
|
|
96
151
|
setIsLoading(true);
|
|
97
152
|
setError(null);
|
|
98
153
|
try {
|
|
99
|
-
const
|
|
100
|
-
return
|
|
154
|
+
const htmlUrl = await stitchService.getScreenHtml(projectId, screenId);
|
|
155
|
+
return htmlUrl;
|
|
101
156
|
} catch (err) {
|
|
102
|
-
const error = err instanceof Error ? err : new Error('Failed to
|
|
157
|
+
const error = err instanceof Error ? err : new Error('Failed to get screen HTML');
|
|
158
|
+
setError(error);
|
|
159
|
+
throw error;
|
|
160
|
+
} finally {
|
|
161
|
+
setIsLoading(false);
|
|
162
|
+
}
|
|
163
|
+
}, []);
|
|
164
|
+
|
|
165
|
+
const getScreenImage = useCallback(async (projectId: string, screenId: string) => {
|
|
166
|
+
setIsLoading(true);
|
|
167
|
+
setError(null);
|
|
168
|
+
try {
|
|
169
|
+
const imageUrl = await stitchService.getScreenImage(projectId, screenId);
|
|
170
|
+
return imageUrl;
|
|
171
|
+
} catch (err) {
|
|
172
|
+
const error = err instanceof Error ? err : new Error('Failed to get screen image');
|
|
173
|
+
setError(error);
|
|
174
|
+
throw error;
|
|
175
|
+
} finally {
|
|
176
|
+
setIsLoading(false);
|
|
177
|
+
}
|
|
178
|
+
}, []);
|
|
179
|
+
|
|
180
|
+
const getScreenOutput = useCallback(async (projectId: string, screenId: string) => {
|
|
181
|
+
setIsLoading(true);
|
|
182
|
+
setError(null);
|
|
183
|
+
try {
|
|
184
|
+
const output = await stitchService.getScreenOutput(projectId, screenId);
|
|
185
|
+
return output;
|
|
186
|
+
} catch (err) {
|
|
187
|
+
const error = err instanceof Error ? err : new Error('Failed to get screen output');
|
|
188
|
+
setError(error);
|
|
189
|
+
throw error;
|
|
190
|
+
} finally {
|
|
191
|
+
setIsLoading(false);
|
|
192
|
+
}
|
|
193
|
+
}, []);
|
|
194
|
+
|
|
195
|
+
const createProject = useCallback(async (title: string) => {
|
|
196
|
+
setIsLoading(true);
|
|
197
|
+
setError(null);
|
|
198
|
+
try {
|
|
199
|
+
const result = await stitchService.createProject(title);
|
|
200
|
+
return result;
|
|
201
|
+
} catch (err) {
|
|
202
|
+
const error = err instanceof Error ? err : new Error('Failed to create project');
|
|
203
|
+
setError(error);
|
|
204
|
+
throw error;
|
|
205
|
+
} finally {
|
|
206
|
+
setIsLoading(false);
|
|
207
|
+
}
|
|
208
|
+
}, []);
|
|
209
|
+
|
|
210
|
+
const callTool = useCallback(async <T = unknown>(name: string, args: Record<string, unknown>) => {
|
|
211
|
+
setIsLoading(true);
|
|
212
|
+
setError(null);
|
|
213
|
+
try {
|
|
214
|
+
const result = await stitchService.callTool<T>(name, args);
|
|
215
|
+
return result;
|
|
216
|
+
} catch (err) {
|
|
217
|
+
const error = err instanceof Error ? err : new Error(`Failed to call tool: ${name}`);
|
|
103
218
|
setError(error);
|
|
104
219
|
throw error;
|
|
105
220
|
} finally {
|
|
@@ -110,10 +225,17 @@ export function useStitch(config?: UseStitchConfig): UseStitchReturn {
|
|
|
110
225
|
return {
|
|
111
226
|
isLoading,
|
|
112
227
|
error,
|
|
113
|
-
readProject,
|
|
114
|
-
writeProject,
|
|
115
|
-
updateProject,
|
|
116
|
-
deleteProject,
|
|
117
228
|
listProjects,
|
|
229
|
+
getProject,
|
|
230
|
+
listScreens,
|
|
231
|
+
getScreen,
|
|
232
|
+
generateScreen,
|
|
233
|
+
editScreen,
|
|
234
|
+
generateVariants,
|
|
235
|
+
getScreenHtml,
|
|
236
|
+
getScreenImage,
|
|
237
|
+
getScreenOutput,
|
|
238
|
+
createProject,
|
|
239
|
+
callTool,
|
|
118
240
|
};
|
|
119
241
|
}
|