@shopify/shop-minis-cli 0.0.161 → 0.0.162
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/build/commands/create-mini/standalone/examples/with-camera-access/.eslintignore +1 -0
- package/build/commands/create-mini/standalone/examples/with-camera-access/.eslintrc.js +3 -0
- package/build/commands/create-mini/standalone/examples/with-camera-access/.graphqlrc.js +1 -0
- package/build/commands/create-mini/standalone/examples/with-camera-access/.prettierrc.json +8 -0
- package/build/commands/create-mini/standalone/examples/with-camera-access/README.md +30 -0
- package/build/commands/create-mini/standalone/examples/with-camera-access/assets.d.ts +14 -0
- package/build/commands/create-mini/standalone/examples/with-camera-access/babel.config.js +5 -0
- package/build/commands/create-mini/standalone/examples/with-camera-access/index.tsx +5 -0
- package/build/commands/create-mini/standalone/examples/with-camera-access/metro.config.js +3 -0
- package/build/commands/create-mini/standalone/examples/with-camera-access/package.json +33 -0
- package/build/commands/create-mini/standalone/examples/with-camera-access/src/App.tsx +152 -0
- package/build/commands/create-mini/standalone/examples/with-camera-access/src/index.tsx +9 -0
- package/build/commands/create-mini/standalone/examples/with-camera-access/src/manifest.json +5 -0
- package/build/commands/create-mini/standalone/examples/with-camera-access/tsconfig.json +41 -0
- package/build/commands/create-mini/standalone/examples/with-fal-ai/.eslintignore +1 -0
- package/build/commands/create-mini/standalone/examples/with-fal-ai/.eslintrc.js +3 -0
- package/build/commands/create-mini/standalone/examples/with-fal-ai/.graphqlrc.js +1 -0
- package/build/commands/create-mini/standalone/examples/with-fal-ai/.prettierrc.json +8 -0
- package/build/commands/create-mini/standalone/examples/with-fal-ai/README.md +46 -0
- package/build/commands/create-mini/standalone/examples/with-fal-ai/assets.d.ts +14 -0
- package/build/commands/create-mini/standalone/examples/with-fal-ai/babel.config.js +5 -0
- package/build/commands/create-mini/standalone/examples/with-fal-ai/index.tsx +5 -0
- package/build/commands/create-mini/standalone/examples/with-fal-ai/metro.config.js +3 -0
- package/build/commands/create-mini/standalone/examples/with-fal-ai/package.json +33 -0
- package/build/commands/create-mini/standalone/examples/with-fal-ai/src/App.tsx +5 -0
- package/build/commands/create-mini/standalone/examples/with-fal-ai/src/index.tsx +9 -0
- package/build/commands/create-mini/standalone/examples/with-fal-ai/src/manifest.json +21 -0
- package/build/commands/create-mini/standalone/examples/with-fal-ai/src/screens/HomeScreen.tsx +142 -0
- package/build/commands/create-mini/standalone/examples/with-fal-ai/tsconfig.json +41 -0
- package/build/commands/create-mini/standalone/examples/with-getting-started/README.md +18 -0
- package/build/commands/create-mini/standalone/examples/with-getting-started/package.json +3 -3
- package/build/commands/create-mini/standalone/examples/with-search/.eslintignore +1 -0
- package/build/commands/create-mini/standalone/examples/with-search/.eslintrc.js +3 -0
- package/build/commands/create-mini/standalone/examples/with-search/.graphqlrc.js +1 -0
- package/build/commands/create-mini/standalone/examples/with-search/.prettierrc.json +8 -0
- package/build/commands/create-mini/standalone/examples/with-search/README.md +25 -0
- package/build/commands/create-mini/standalone/examples/with-search/assets.d.ts +14 -0
- package/build/commands/create-mini/standalone/examples/with-search/babel.config.js +5 -0
- package/build/commands/create-mini/standalone/examples/with-search/index.tsx +5 -0
- package/build/commands/create-mini/standalone/examples/with-search/metro.config.js +3 -0
- package/build/commands/create-mini/standalone/examples/with-search/package.json +33 -0
- package/build/commands/create-mini/standalone/examples/with-search/src/App.tsx +23 -0
- package/build/commands/create-mini/standalone/examples/with-search/src/components/HeaderAction.tsx +32 -0
- package/build/commands/create-mini/standalone/examples/with-search/src/components/ShopCard.tsx +92 -0
- package/build/commands/create-mini/standalone/examples/with-search/src/index.tsx +9 -0
- package/build/commands/create-mini/standalone/examples/with-search/src/manifest.json +7 -0
- package/build/commands/create-mini/standalone/examples/with-search/src/screens/MerchantSearchScreen.tsx +126 -0
- package/build/commands/create-mini/standalone/examples/with-search/src/screens/ProductSearchScreen.tsx +115 -0
- package/build/commands/create-mini/standalone/examples/with-search/src/types/screens.ts +6 -0
- package/build/commands/create-mini/standalone/examples/with-search/tsconfig.json +41 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/.eslintignore +1 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/.eslintrc.js +3 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/.graphqlrc.js +1 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/.prettierrc.json +8 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/README.md +26 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/assets.d.ts +14 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/babel.config.js +5 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/index.tsx +5 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/metro.config.js +3 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/package.json +33 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/src/App.tsx +5 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/src/components/ProductSection.tsx +39 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/src/components/SectionStyles.ts +9 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/src/components/ShopCard.tsx +42 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/src/components/ShopSection.tsx +40 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/src/index.tsx +9 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/src/manifest.json +10 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/src/screens/HomeScreen.tsx +67 -0
- package/build/commands/create-mini/standalone/examples/with-user-data/tsconfig.json +41 -0
- package/build/commands/create-mini/standalone/index.js +11 -4
- package/build/commands/create-mini/standalone/index.js.map +1 -1
- package/build/commands/create-mini/utils/examples.d.ts +3 -3
- package/build/commands/create-mini/utils/examples.js +16 -7
- package/build/commands/create-mini/utils/examples.js.map +1 -1
- package/build/commands/create-mini/utils/index.js.map +1 -1
- package/build/utils/package-manager.d.ts +7 -0
- package/build/utils/package-manager.js +15 -0
- package/build/utils/package-manager.js.map +1 -1
- package/package.json +1 -1
- package/scripts/test-create-mini-standalone.ts +24 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*.graphql.d.ts
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('@shopify/shop-minis-sdk/graphqlrc')
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Camera Access Mini
|
|
2
|
+
|
|
3
|
+
A Shop Mini that demonstrates device camera access, photo gallery selection, and photo sharing capabilities.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Access device camera to take photos
|
|
8
|
+
- Access photo gallery to select existing photos
|
|
9
|
+
- Display selected/captured photos
|
|
10
|
+
- Share photos using the device's native share sheet
|
|
11
|
+
- Built with React Native components and styling
|
|
12
|
+
|
|
13
|
+
## Setup
|
|
14
|
+
|
|
15
|
+
1. Run the development server:
|
|
16
|
+
```bash
|
|
17
|
+
npm start
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Development
|
|
21
|
+
|
|
22
|
+
This mini is built using:
|
|
23
|
+
|
|
24
|
+
- React Native
|
|
25
|
+
- TypeScript
|
|
26
|
+
- Shop Minis SDK
|
|
27
|
+
- react-native-image-crop-picker - for camera and gallery access
|
|
28
|
+
- react-native-share - for native share sheet functionality
|
|
29
|
+
|
|
30
|
+
Note: Camera access requires running the app on a physical device.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
declare module '*.svg' {
|
|
2
|
+
const content: import('react').FC<import('react-native-svg').SvgProps>
|
|
3
|
+
export default content
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
declare module '*.png' {
|
|
7
|
+
const content: import('react-native').ImageRequireSource
|
|
8
|
+
export default content
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
declare module '*.jpg' {
|
|
12
|
+
const content: import('react-native').ImageRequireSource
|
|
13
|
+
export default content
|
|
14
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
// Changes to babel config are not supported by the mini platform.
|
|
3
|
+
// Custom configuration can introduce unexpected behaviour in your mini and could be a cause of rejection during the submission process.
|
|
4
|
+
presets: ['@shopify/shop-minis-sdk/babel-preset'],
|
|
5
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "with-camera-access",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"start": "shop-minis dev",
|
|
7
|
+
"test": "jest",
|
|
8
|
+
"lint": "eslint ."
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@shopify/shop-minis-sdk": "0.0.16"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@shopify/shop-minis-cli": "0.0.161",
|
|
15
|
+
"@types/jest": "^29.2.6",
|
|
16
|
+
"babel-jest": "^26.6.3",
|
|
17
|
+
"eslint": "^8.32.0",
|
|
18
|
+
"jest": "^29.3.1",
|
|
19
|
+
"prettier": "^2.8.2"
|
|
20
|
+
},
|
|
21
|
+
"jest": {
|
|
22
|
+
"preset": "react-native"
|
|
23
|
+
},
|
|
24
|
+
"overrides": {
|
|
25
|
+
"graphql": "15.8.0",
|
|
26
|
+
"react": "18.2.0",
|
|
27
|
+
"react-native": "0.73.2"
|
|
28
|
+
},
|
|
29
|
+
"resolutions": {
|
|
30
|
+
"@apollo/federation": "0.38.1",
|
|
31
|
+
"graphql": "15.8.0"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import {useState} from 'react'
|
|
2
|
+
import {View, Text, TouchableOpacity, StyleSheet} from 'react-native'
|
|
3
|
+
import {
|
|
4
|
+
SafeAreaView,
|
|
5
|
+
ImageBox,
|
|
6
|
+
useErrorToast,
|
|
7
|
+
useImagePicker,
|
|
8
|
+
useShare,
|
|
9
|
+
} from '@shopify/shop-minis-sdk'
|
|
10
|
+
|
|
11
|
+
function Button({
|
|
12
|
+
text,
|
|
13
|
+
onPress,
|
|
14
|
+
variant = 'primary',
|
|
15
|
+
disabled,
|
|
16
|
+
style,
|
|
17
|
+
}: {
|
|
18
|
+
text: string
|
|
19
|
+
onPress: () => void
|
|
20
|
+
variant?: 'primary' | 'secondary'
|
|
21
|
+
disabled?: boolean
|
|
22
|
+
style?: object
|
|
23
|
+
}) {
|
|
24
|
+
return (
|
|
25
|
+
<TouchableOpacity
|
|
26
|
+
disabled={disabled}
|
|
27
|
+
style={[
|
|
28
|
+
styles.button,
|
|
29
|
+
variant === 'primary' ? styles.primaryButton : styles.secondaryButton,
|
|
30
|
+
disabled && {opacity: 0.5},
|
|
31
|
+
style,
|
|
32
|
+
]}
|
|
33
|
+
onPress={onPress}
|
|
34
|
+
>
|
|
35
|
+
<Text
|
|
36
|
+
style={[
|
|
37
|
+
styles.buttonText,
|
|
38
|
+
{color: variant === 'primary' ? '#FFFFFF' : '#000000'},
|
|
39
|
+
]}
|
|
40
|
+
>
|
|
41
|
+
{text}
|
|
42
|
+
</Text>
|
|
43
|
+
</TouchableOpacity>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function App() {
|
|
48
|
+
const [imageUrl, setImageUrl] = useState<string>()
|
|
49
|
+
const {showErrorToast} = useErrorToast()
|
|
50
|
+
const {openCamera, openPicker} = useImagePicker()
|
|
51
|
+
const {share} = useShare()
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<SafeAreaView style={{flex: 1}}>
|
|
55
|
+
<View
|
|
56
|
+
style={{flex: 1, paddingHorizontal: 16, backgroundColor: '#FFFFFF'}}
|
|
57
|
+
>
|
|
58
|
+
<Text style={styles.title}>Share a Photo</Text>
|
|
59
|
+
<Text style={styles.subtitle}>
|
|
60
|
+
Let's explore the native capabilities your Shop Mini can access.
|
|
61
|
+
</Text>
|
|
62
|
+
<View>
|
|
63
|
+
<Button
|
|
64
|
+
text="Camera access"
|
|
65
|
+
onPress={async () => {
|
|
66
|
+
await openCamera({})
|
|
67
|
+
.then(image => setImageUrl(image.path))
|
|
68
|
+
.catch(error => {
|
|
69
|
+
showErrorToast({
|
|
70
|
+
message: error.message,
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
}}
|
|
74
|
+
/>
|
|
75
|
+
<Text style={{marginTop: 8}}>
|
|
76
|
+
Run this Mini on a real device to access the camera.
|
|
77
|
+
</Text>
|
|
78
|
+
</View>
|
|
79
|
+
<View style={{marginVertical: 16}}>
|
|
80
|
+
<Button
|
|
81
|
+
text="Gallery access"
|
|
82
|
+
variant="secondary"
|
|
83
|
+
onPress={async () => {
|
|
84
|
+
await openPicker({})
|
|
85
|
+
.then(image => setImageUrl(image.path))
|
|
86
|
+
.catch(console.log)
|
|
87
|
+
}}
|
|
88
|
+
/>
|
|
89
|
+
</View>
|
|
90
|
+
{imageUrl ? (
|
|
91
|
+
<View style={{marginTop: 32, alignItems: 'center'}}>
|
|
92
|
+
<View style={styles.imageContainer}>
|
|
93
|
+
<ImageBox source={{uri: imageUrl}} style={styles.image} />
|
|
94
|
+
</View>
|
|
95
|
+
<Button
|
|
96
|
+
text="Share photo"
|
|
97
|
+
variant="secondary"
|
|
98
|
+
disabled={!imageUrl}
|
|
99
|
+
style={{width: 200, marginTop: 16}}
|
|
100
|
+
onPress={async () => {
|
|
101
|
+
if (imageUrl) {
|
|
102
|
+
await share({
|
|
103
|
+
url: imageUrl,
|
|
104
|
+
title: 'My Shared Image',
|
|
105
|
+
type: 'image/*',
|
|
106
|
+
}).catch(console.log)
|
|
107
|
+
}
|
|
108
|
+
}}
|
|
109
|
+
/>
|
|
110
|
+
</View>
|
|
111
|
+
) : null}
|
|
112
|
+
</View>
|
|
113
|
+
</SafeAreaView>
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const styles = StyleSheet.create({
|
|
118
|
+
button: {
|
|
119
|
+
padding: 12,
|
|
120
|
+
borderRadius: 8,
|
|
121
|
+
alignItems: 'center',
|
|
122
|
+
},
|
|
123
|
+
primaryButton: {
|
|
124
|
+
backgroundColor: '#000000',
|
|
125
|
+
},
|
|
126
|
+
secondaryButton: {
|
|
127
|
+
backgroundColor: '#E6E6E6',
|
|
128
|
+
},
|
|
129
|
+
buttonText: {
|
|
130
|
+
fontSize: 16,
|
|
131
|
+
},
|
|
132
|
+
title: {
|
|
133
|
+
fontSize: 24,
|
|
134
|
+
fontWeight: 'bold',
|
|
135
|
+
marginBottom: 16,
|
|
136
|
+
marginTop: 8,
|
|
137
|
+
},
|
|
138
|
+
subtitle: {
|
|
139
|
+
fontSize: 16,
|
|
140
|
+
marginBottom: 16,
|
|
141
|
+
},
|
|
142
|
+
imageContainer: {
|
|
143
|
+
width: 200,
|
|
144
|
+
height: 200,
|
|
145
|
+
borderRadius: 16,
|
|
146
|
+
overflow: 'hidden',
|
|
147
|
+
},
|
|
148
|
+
image: {
|
|
149
|
+
width: 200,
|
|
150
|
+
height: 200,
|
|
151
|
+
},
|
|
152
|
+
})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"baseUrl": ".",
|
|
4
|
+
"paths": {
|
|
5
|
+
"*": [
|
|
6
|
+
"*",
|
|
7
|
+
"*.ios",
|
|
8
|
+
"*.android",
|
|
9
|
+
"./node_modules/@shopify/shop-minis-sdk/node_modules/*"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
"allowJs": true,
|
|
13
|
+
"resolveJsonModule": true,
|
|
14
|
+
"allowSyntheticDefaultImports": true,
|
|
15
|
+
"esModuleInterop": true,
|
|
16
|
+
"isolatedModules": false,
|
|
17
|
+
"jsx": "preserve",
|
|
18
|
+
"lib": ["es2019"],
|
|
19
|
+
"noUnusedParameters": true,
|
|
20
|
+
"noUnusedLocals": true,
|
|
21
|
+
"moduleResolution": "node",
|
|
22
|
+
"noEmit": true,
|
|
23
|
+
"incremental": true,
|
|
24
|
+
"strict": true,
|
|
25
|
+
"target": "esnext",
|
|
26
|
+
"skipLibCheck": true,
|
|
27
|
+
"noImplicitReturns": false,
|
|
28
|
+
"noFallthroughCasesInSwitch": true,
|
|
29
|
+
"allowUnreachableCode": false,
|
|
30
|
+
"allowUnusedLabels": false,
|
|
31
|
+
"noImplicitAny": true,
|
|
32
|
+
"strictNullChecks": true,
|
|
33
|
+
"strictFunctionTypes": true,
|
|
34
|
+
"strictBindCallApply": true,
|
|
35
|
+
"strictPropertyInitialization": true,
|
|
36
|
+
"noImplicitThis": true,
|
|
37
|
+
"alwaysStrict": true,
|
|
38
|
+
"useUnknownInCatchVariables": false
|
|
39
|
+
},
|
|
40
|
+
"exclude": ["node_modules"]
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*.graphql.d.ts
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('@shopify/shop-minis-sdk/graphqlrc')
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Product AI Image Generator Mini
|
|
2
|
+
|
|
3
|
+
A Shop Mini that generates AI-powered product images based on your recently viewed products. Using FAL AI's image generation capabilities, this mini creates realistic studio-quality product images from product titles, descriptions, and shop information.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Automatically detects your most recently viewed product
|
|
8
|
+
- Generates AI-powered product images using FAL AI
|
|
9
|
+
- Displays original product information alongside generated images
|
|
10
|
+
- Simple one-click image generation
|
|
11
|
+
|
|
12
|
+
## Setup
|
|
13
|
+
|
|
14
|
+
1. Clone this repository
|
|
15
|
+
2. Install dependencies:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
3. Setup your mini and login with your partners account:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx shop-minis setup
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
4. Set up your FAL AI API key:
|
|
28
|
+
|
|
29
|
+
- Sign up for a FAL AI account at [FAL AI](https://fal.ai)
|
|
30
|
+
- Get your API key from the dashboard
|
|
31
|
+
- Run `npx shop-minis secrets set fal_ai_key <your-api-key-here>`
|
|
32
|
+
- Run `npx shop-minis proxies apply`
|
|
33
|
+
|
|
34
|
+
5. Run the development server:
|
|
35
|
+
```bash
|
|
36
|
+
npm start
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Development
|
|
40
|
+
|
|
41
|
+
This mini is built using:
|
|
42
|
+
|
|
43
|
+
- React Native
|
|
44
|
+
- TypeScript
|
|
45
|
+
- Shop Minis SDK
|
|
46
|
+
- FAL AI API
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
declare module '*.svg' {
|
|
2
|
+
const content: import('react').FC<import('react-native-svg').SvgProps>
|
|
3
|
+
export default content
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
declare module '*.png' {
|
|
7
|
+
const content: import('react-native').ImageRequireSource
|
|
8
|
+
export default content
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
declare module '*.jpg' {
|
|
12
|
+
const content: import('react-native').ImageRequireSource
|
|
13
|
+
export default content
|
|
14
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
// Changes to babel config are not supported by the mini platform.
|
|
3
|
+
// Custom configuration can introduce unexpected behaviour in your mini and could be a cause of rejection during the submission process.
|
|
4
|
+
presets: ['@shopify/shop-minis-sdk/babel-preset'],
|
|
5
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "with-fal-ai",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"start": "shop-minis dev",
|
|
7
|
+
"test": "jest",
|
|
8
|
+
"lint": "eslint ."
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@shopify/shop-minis-sdk": "0.0.16"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@shopify/shop-minis-cli": "0.0.161",
|
|
15
|
+
"@types/jest": "^29.2.6",
|
|
16
|
+
"babel-jest": "^26.6.3",
|
|
17
|
+
"eslint": "^8.32.0",
|
|
18
|
+
"jest": "^29.3.1",
|
|
19
|
+
"prettier": "^2.8.2"
|
|
20
|
+
},
|
|
21
|
+
"jest": {
|
|
22
|
+
"preset": "react-native"
|
|
23
|
+
},
|
|
24
|
+
"overrides": {
|
|
25
|
+
"graphql": "15.8.0",
|
|
26
|
+
"react": "18.2.0",
|
|
27
|
+
"react-native": "0.73.2"
|
|
28
|
+
},
|
|
29
|
+
"resolutions": {
|
|
30
|
+
"@apollo/federation": "0.38.1",
|
|
31
|
+
"graphql": "15.8.0"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "with-fal-ai",
|
|
3
|
+
"features": ["FULL_BLEED_VIEWER", "STANDALONE"],
|
|
4
|
+
"trusted_domains": ["v3.fal.media"],
|
|
5
|
+
"proxies": [
|
|
6
|
+
{
|
|
7
|
+
"target_url_pattern": "https://queue.fal.run/fal-ai/flux/schnell*",
|
|
8
|
+
"allowed_methods": ["POST"],
|
|
9
|
+
"appended_headers": ["Authorization: Key {{ secrets.fal_ai_key }}"],
|
|
10
|
+
"user_rate_limit_requests": 10,
|
|
11
|
+
"user_rate_limit_interval": 3600
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"target_url_pattern": "https://queue.fal.run/fal-ai/flux/requests*",
|
|
15
|
+
"allowed_methods": ["GET"],
|
|
16
|
+
"appended_headers": ["Authorization: Key {{ secrets.fal_ai_key }}"],
|
|
17
|
+
"user_rate_limit_requests": 50,
|
|
18
|
+
"user_rate_limit_interval": 300
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import {useState} from 'react'
|
|
2
|
+
import {ScrollView, View, Text, Button, StyleSheet} from 'react-native'
|
|
3
|
+
import {
|
|
4
|
+
SafeAreaView,
|
|
5
|
+
ProductCard,
|
|
6
|
+
useRecentProducts,
|
|
7
|
+
Product,
|
|
8
|
+
Image,
|
|
9
|
+
useFalAi,
|
|
10
|
+
} from '@shopify/shop-minis-sdk'
|
|
11
|
+
|
|
12
|
+
function generatePrompt(product: Product): string {
|
|
13
|
+
return `
|
|
14
|
+
A realistic Product image photo in a studio setting of a product named ${product.title} from the store: ${product.shop.name}
|
|
15
|
+
`
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function EmptyState() {
|
|
19
|
+
return (
|
|
20
|
+
<Text>
|
|
21
|
+
No recently viewed products found. Close the Mini and visit any product.
|
|
22
|
+
</Text>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function ProductSection({
|
|
27
|
+
product,
|
|
28
|
+
isLoading,
|
|
29
|
+
onGenerateImage,
|
|
30
|
+
}: {
|
|
31
|
+
product: Product
|
|
32
|
+
isLoading: boolean
|
|
33
|
+
onGenerateImage: () => void
|
|
34
|
+
}) {
|
|
35
|
+
return (
|
|
36
|
+
<>
|
|
37
|
+
<Text style={styles.title}>Generate an AI image from this product</Text>
|
|
38
|
+
<Text>
|
|
39
|
+
Based on the product title, shop and description, this mini generates a
|
|
40
|
+
realistic image of the product.
|
|
41
|
+
</Text>
|
|
42
|
+
<View style={styles.productContainer}>
|
|
43
|
+
<ProductCard product={product} />
|
|
44
|
+
</View>
|
|
45
|
+
<Button
|
|
46
|
+
disabled={isLoading}
|
|
47
|
+
onPress={onGenerateImage}
|
|
48
|
+
title={isLoading ? 'Loading...' : 'Generate an AI image'}
|
|
49
|
+
/>
|
|
50
|
+
</>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function HomeScreen() {
|
|
55
|
+
const {products} = useRecentProducts({first: 1})
|
|
56
|
+
const fal = useFalAi()
|
|
57
|
+
const [imageUrl, setImageUrl] = useState('')
|
|
58
|
+
const [isLoading, setIsLoading] = useState(false)
|
|
59
|
+
|
|
60
|
+
const generateImage = async () => {
|
|
61
|
+
const product = products?.[0]
|
|
62
|
+
if (!product) return
|
|
63
|
+
|
|
64
|
+
setIsLoading(true)
|
|
65
|
+
setImageUrl('')
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
const prompt = generatePrompt(product)
|
|
69
|
+
const response = await fal.subscribe('fal-ai/flux/schnell', {
|
|
70
|
+
input: {
|
|
71
|
+
prompt,
|
|
72
|
+
},
|
|
73
|
+
mode: 'polling',
|
|
74
|
+
pollInterval: 1000,
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
if (response.data.images?.[0]?.url) {
|
|
78
|
+
setImageUrl(response.data.images[0].url)
|
|
79
|
+
}
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error('Failed to generateImage:', error)
|
|
82
|
+
} finally {
|
|
83
|
+
setIsLoading(false)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<SafeAreaView>
|
|
89
|
+
<ScrollView>
|
|
90
|
+
<View style={styles.container}>
|
|
91
|
+
<View style={styles.main}>
|
|
92
|
+
{(() => {
|
|
93
|
+
if (products === undefined) return null
|
|
94
|
+
if (products.length === 0) return <EmptyState />
|
|
95
|
+
return (
|
|
96
|
+
<ProductSection
|
|
97
|
+
product={products[0]}
|
|
98
|
+
isLoading={isLoading}
|
|
99
|
+
onGenerateImage={generateImage}
|
|
100
|
+
/>
|
|
101
|
+
)
|
|
102
|
+
})()}
|
|
103
|
+
|
|
104
|
+
{imageUrl ? (
|
|
105
|
+
<Image source={{uri: imageUrl}} style={styles.generatedImage} />
|
|
106
|
+
) : null}
|
|
107
|
+
</View>
|
|
108
|
+
</View>
|
|
109
|
+
</ScrollView>
|
|
110
|
+
</SafeAreaView>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const styles = StyleSheet.create({
|
|
115
|
+
container: {
|
|
116
|
+
flex: 1,
|
|
117
|
+
alignItems: 'stretch',
|
|
118
|
+
justifyContent: 'center',
|
|
119
|
+
marginHorizontal: 'auto',
|
|
120
|
+
},
|
|
121
|
+
main: {
|
|
122
|
+
gap: 8,
|
|
123
|
+
justifyContent: 'center',
|
|
124
|
+
alignItems: 'stretch',
|
|
125
|
+
paddingHorizontal: 24,
|
|
126
|
+
},
|
|
127
|
+
title: {
|
|
128
|
+
marginVertical: 10,
|
|
129
|
+
fontSize: 24,
|
|
130
|
+
fontWeight: 'bold',
|
|
131
|
+
},
|
|
132
|
+
productContainer: {
|
|
133
|
+
marginHorizontal: 50,
|
|
134
|
+
},
|
|
135
|
+
generatedImage: {
|
|
136
|
+
width: '100%',
|
|
137
|
+
height: 300,
|
|
138
|
+
marginTop: 12,
|
|
139
|
+
marginBottom: 20,
|
|
140
|
+
borderRadius: 8,
|
|
141
|
+
},
|
|
142
|
+
})
|