vibefast-cli 0.7.13 → 0.7.14
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/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +27 -1
- package/dist/commands/add.js.map +1 -1
- package/package.json +1 -1
- package/recipes/audio-recorder/recipe.json +1 -1
- package/recipes/audio-recorder@latest.zip +0 -0
- package/recipes/charts/apps/native/src/app/{charts → (root)/(protected)/charts}/index.tsx +0 -3
- package/recipes/charts/apps/native/src/features/charts/app/preview.tsx +0 -3
- package/recipes/charts/apps/native/src/features/charts/components/area-chart.tsx +0 -3
- package/recipes/charts/apps/native/src/features/charts/components/bar-chart.tsx +0 -3
- package/recipes/charts/apps/native/src/features/charts/components/candlestick-chart.tsx +0 -3
- package/recipes/charts/apps/native/src/features/charts/components/chart-card.tsx +0 -3
- package/recipes/charts/apps/native/src/features/charts/components/column-chart.tsx +0 -3
- package/recipes/charts/apps/native/src/features/charts/components/doughnut-chart.tsx +0 -3
- package/recipes/charts/apps/native/src/features/charts/components/index.ts +0 -3
- package/recipes/charts/apps/native/src/features/charts/components/line-chart.tsx +0 -3
- package/recipes/charts/apps/native/src/features/charts/components/radar-chart.tsx +0 -3
- package/recipes/charts/apps/native/src/features/charts/components/radial-bar-chart.tsx +0 -3
- package/recipes/charts/apps/native/src/features/charts/components/stacked-area-chart.tsx +0 -3
- package/recipes/charts/apps/native/src/features/charts/components/stacked-bar-chart.tsx +0 -3
- package/recipes/charts/apps/native/src/features/charts/data/mock-data.ts +0 -3
- package/recipes/charts/apps/native/src/features/charts/types/index.ts +0 -3
- package/recipes/charts/recipe.json +1 -1
- package/recipes/charts@latest.zip +0 -0
- package/recipes/chatbot/apps/native/src/api-client/chatbot.ts +83 -0
- package/recipes/chatbot/apps/native/src/app/{chatbot → (root)/(protected)/chatbot}/index.tsx +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/app/index.tsx +56 -60
- package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-header-buttons.tsx +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-input-bar.tsx +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-markdown.tsx +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-message-bubble.tsx +3 -26
- package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-settings-modal.tsx +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/components/image-preview-list.tsx +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/code-block.tsx +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/index.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/table-renderer.tsx +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/components/message-error-boundary.tsx +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/components/message-list.tsx +10 -14
- package/recipes/chatbot/apps/native/src/features/chatbot/components/model-selector.tsx +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/components/report-content-modal.tsx +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/components/suggested-messages.tsx +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/constants/models.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/constants/report-reasons.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-attachment-cache.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-chat-config.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-chat-handlers.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-chatbot-settings.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-conversation.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-image-picker.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-keyboard-coordinator.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/hooks/use-smart-scroll-manager.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/models/index.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/models/models.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/models/providers.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/models/types.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/services/file-uploader.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/services/message-handler-service.ts +0 -1
- package/recipes/chatbot/apps/native/src/features/chatbot/types/index.ts +5 -3
- package/recipes/chatbot/apps/native/src/features/chatbot/utils/chat-telemetry.ts +0 -1
- package/recipes/chatbot/packages/backend/convex/agents.ts +3 -4
- package/recipes/chatbot/packages/backend/convex/chatbot/content.ts +35 -0
- package/recipes/chatbot/packages/backend/convex/chatbot/sessions.ts +52 -0
- package/recipes/chatbot/packages/backend/convex/chatbot/streaming.ts +422 -0
- package/recipes/chatbot/packages/backend/convex/chatbot/telemetry.ts +56 -0
- package/recipes/chatbot/packages/backend/convex/chatbot/tools.ts +128 -0
- package/recipes/chatbot/packages/backend/convex/chatbotAgent.ts +6 -651
- package/recipes/chatbot/packages/backend/convex/ragKnowledge.ts +0 -714
- package/recipes/chatbot/packages/backend/convex/tools/knowledgeRetrieval.ts +12 -7
- package/recipes/chatbot/recipe.json +6 -1
- package/recipes/chatbot@latest.zip +0 -0
- package/recipes/image-generator/apps/native/src/api-client/image-generator.ts +34 -0
- package/recipes/image-generator/packages/backend/convex/{imageGeneratorFunctions.ts → imageGenerator.ts} +1 -1
- package/recipes/image-generator/recipe.json +5 -1
- package/recipes/image-generator@latest.zip +0 -0
- package/recipes/payments/apps/native/src/api-client/payments.ts +44 -0
- package/recipes/payments/packages/backend/convex/payments/index.ts +13 -0
- package/recipes/payments/packages/backend/convex/payments.ts +119 -0
- package/recipes/payments/recipe.json +15 -2
- package/recipes/payments@latest.zip +0 -0
- package/recipes/quiz/recipe.json +1 -1
- package/recipes/quiz@latest.zip +0 -0
- package/recipes/tracker-app/recipe.json +1 -1
- package/recipes/tracker-app@latest.zip +0 -0
- package/recipes/voice-bot/recipe.json +1 -1
- package/recipes/voice-bot@latest.zip +0 -0
- package/src/commands/add.ts +39 -1
- package/tmp-npm-cache/_update-notifier-last-checked +0 -0
- /package/recipes/audio-recorder/apps/native/src/app/{audio-recorder → (root)/(protected)/audio-recorder}/index.tsx +0 -0
- /package/recipes/image-generator/apps/native/src/app/{image-generator → (root)/(protected)/image-generator}/gallery.tsx +0 -0
- /package/recipes/image-generator/apps/native/src/app/{image-generator → (root)/(protected)/image-generator}/index.tsx +0 -0
- /package/recipes/quiz/apps/native/src/app/{quiz → (root)/(protected)/quiz}/index.tsx +0 -0
- /package/recipes/tracker-app/apps/native/src/app/{tracker-app → (root)/(protected)/tracker-app}/index.tsx +0 -0
- /package/recipes/voice-bot/apps/native/src/app/{voice-bot → (root)/(protected)/voice-bot}/index.tsx +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
import { createTool } from '@convex-dev/agent';
|
|
2
3
|
import { z } from 'zod';
|
|
3
4
|
|
|
@@ -65,13 +66,16 @@ export const knowledgeRetrievalTool = createTool({
|
|
|
65
66
|
after: args.chunkContext?.after ?? 1,
|
|
66
67
|
};
|
|
67
68
|
|
|
68
|
-
const result = (await ctx.runAction(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
const result = (await (ctx as any).runAction(
|
|
70
|
+
(api as any).ragKnowledge.askKnowledge,
|
|
71
|
+
{
|
|
72
|
+
prompt,
|
|
73
|
+
globalNamespace: args.scope === 'global',
|
|
74
|
+
limit: args.limit,
|
|
75
|
+
chunkContext,
|
|
76
|
+
filter,
|
|
77
|
+
} as any,
|
|
78
|
+
)) as {
|
|
75
79
|
answer: string;
|
|
76
80
|
files?: { filename: string; url: string | null }[];
|
|
77
81
|
};
|
|
@@ -90,3 +94,4 @@ export const knowledgeRetrievalTool = createTool({
|
|
|
90
94
|
return `${result.answer}\n\n**References**\n${references}`;
|
|
91
95
|
},
|
|
92
96
|
});
|
|
97
|
+
// @ts-nocheck
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chatbot",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "AI-powered chat assistant",
|
|
5
5
|
"copy": [
|
|
6
6
|
{
|
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
"from": "apps/native/src/features/chatbot",
|
|
12
12
|
"to": "apps/native/src/features/chatbot"
|
|
13
13
|
},
|
|
14
|
+
{
|
|
15
|
+
"from": "apps/native/src/api-client/chatbot.ts",
|
|
16
|
+
"to": "apps/native/src/api-client/chatbot.ts"
|
|
17
|
+
},
|
|
14
18
|
{
|
|
15
19
|
"from": "packages/backend/convex/chatbot",
|
|
16
20
|
"to": "packages/backend/convex/chatbot"
|
|
@@ -69,6 +73,7 @@
|
|
|
69
73
|
"expo-clipboard",
|
|
70
74
|
"markdown-it",
|
|
71
75
|
"react-native-markdown-display",
|
|
76
|
+
"react-native-syntax-highlighter",
|
|
72
77
|
"react-syntax-highlighter",
|
|
73
78
|
"react-native-reanimated",
|
|
74
79
|
"react-native-safe-area-context"
|
|
Binary file
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { api } from '@vibefast/backend/_generated/api';
|
|
2
|
+
import { useAction } from 'convex/react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Image Generator API Gateway
|
|
6
|
+
*
|
|
7
|
+
* This gateway provides typed wrappers around Convex image generation functions.
|
|
8
|
+
* It handles AI-powered image generation backed by the AI SDK providers.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* - Import this gateway in feature code: `import { imageGeneratorApi } from '@/platform/api/image-generator'`
|
|
12
|
+
* - Never import from `@vibefast/backend/_generated/api` directly in feature code
|
|
13
|
+
*/
|
|
14
|
+
export const imageGeneratorApi = {
|
|
15
|
+
/**
|
|
16
|
+
* Generate an image based on user prompt and provider selection
|
|
17
|
+
*
|
|
18
|
+
* @returns Promise with image data URI, mime type, and metadata
|
|
19
|
+
*/
|
|
20
|
+
useGenerateImage() {
|
|
21
|
+
const action = useAction(api['imageGeneration/index'].generateImageAction);
|
|
22
|
+
|
|
23
|
+
return (args: GenerateImageArgs) =>
|
|
24
|
+
action(args as Parameters<typeof action>[0]);
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type ImageGeneratorApi = typeof imageGeneratorApi;
|
|
29
|
+
|
|
30
|
+
export type GenerateImageArgs = {
|
|
31
|
+
prompt: string;
|
|
32
|
+
provider: string;
|
|
33
|
+
model: string;
|
|
34
|
+
};
|
|
@@ -63,7 +63,7 @@ const generateWithOpenAI = async (prompt: string, model: string) => {
|
|
|
63
63
|
throw new Error('OpenAI image generation did not return any image data.');
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
const mimeType = imageResult.mimeType ?? 'image/png';
|
|
66
|
+
const mimeType = (imageResult as any).mimeType ?? 'image/png';
|
|
67
67
|
const base64Data =
|
|
68
68
|
imageResult.base64 ??
|
|
69
69
|
(imageResult.uint8Array
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "image-generator",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "AI-powered image generation",
|
|
5
5
|
"copy": [
|
|
6
6
|
{
|
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
"from": "apps/native/src/features/image-generator",
|
|
12
12
|
"to": "apps/native/src/features/image-generator"
|
|
13
13
|
},
|
|
14
|
+
{
|
|
15
|
+
"from": "apps/native/src/api-client/image-generator.ts",
|
|
16
|
+
"to": "apps/native/src/api-client/image-generator.ts"
|
|
17
|
+
},
|
|
14
18
|
{
|
|
15
19
|
"from": "packages/backend/convex/imageGeneration/index.ts",
|
|
16
20
|
"to": "packages/backend/convex/imageGeneration/index.ts"
|
|
Binary file
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { api } from '@vibefast/backend/_generated/api';
|
|
2
|
+
import { useMutation, useQuery } from 'convex/react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Payments API Gateway
|
|
6
|
+
*
|
|
7
|
+
* This gateway provides typed wrappers around Convex payment functions.
|
|
8
|
+
* It handles RevenueCat purchases, credit management, and purchase history.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* - Import this gateway in feature code: `import { paymentsApi } from '@/platform/api/payments'`
|
|
12
|
+
* - Never import from `@vibefast/backend/_generated/api` directly in feature code
|
|
13
|
+
*/
|
|
14
|
+
export const paymentsApi = {
|
|
15
|
+
/**
|
|
16
|
+
* Record a consumable purchase (like credits) in the database
|
|
17
|
+
*/
|
|
18
|
+
useRecordConsumablePurchase() {
|
|
19
|
+
return useMutation(api['payments/index'].recordConsumablePurchase);
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get user's current credit balance
|
|
24
|
+
*/
|
|
25
|
+
useGetUserCredits() {
|
|
26
|
+
return useQuery(api['payments/index'].getUserCredits);
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get user's purchase history with pagination
|
|
31
|
+
*/
|
|
32
|
+
useGetPurchaseHistory(
|
|
33
|
+
paginationOpts: { numItems: number; cursor: string | null } = {
|
|
34
|
+
numItems: 50,
|
|
35
|
+
cursor: null,
|
|
36
|
+
},
|
|
37
|
+
) {
|
|
38
|
+
return useQuery(api['payments/index'].getPurchaseHistory, {
|
|
39
|
+
paginationOpts,
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export type PaymentsApi = typeof paymentsApi;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payments Domain Aggregator
|
|
3
|
+
*
|
|
4
|
+
* Single entry point for all payment-related Convex functions.
|
|
5
|
+
* Re-exports functions from payments.ts to decouple
|
|
6
|
+
* frontend from internal file structure.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
getPurchaseHistory,
|
|
11
|
+
getUserCredits,
|
|
12
|
+
recordConsumablePurchase,
|
|
13
|
+
} from '../payments';
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { getAuthUserId } from '@convex-dev/auth/server';
|
|
2
|
+
import { v } from 'convex/values';
|
|
3
|
+
|
|
4
|
+
import { mutation, query } from './_generated/server';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Record a consumable purchase (like credits) in the database
|
|
8
|
+
*/
|
|
9
|
+
export const recordConsumablePurchase = mutation({
|
|
10
|
+
args: {
|
|
11
|
+
productId: v.string(),
|
|
12
|
+
quantity: v.number(),
|
|
13
|
+
},
|
|
14
|
+
returns: v.object({
|
|
15
|
+
success: v.boolean(),
|
|
16
|
+
newCredits: v.number(),
|
|
17
|
+
totalCredits: v.number(),
|
|
18
|
+
}),
|
|
19
|
+
handler: async (ctx, args) => {
|
|
20
|
+
const userId = await getAuthUserId(ctx);
|
|
21
|
+
if (!userId) {
|
|
22
|
+
throw new Error('Not authenticated');
|
|
23
|
+
}
|
|
24
|
+
// Get current user to check existing credits
|
|
25
|
+
const user = await ctx.db.get(userId);
|
|
26
|
+
if (!user) {
|
|
27
|
+
throw new Error('User not found');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Calculate new credits based on product
|
|
31
|
+
let creditsToAdd = args.quantity;
|
|
32
|
+
|
|
33
|
+
// You can customize credit amounts based on productId
|
|
34
|
+
if (args.productId.includes('premium')) {
|
|
35
|
+
creditsToAdd = args.quantity * 2; // Premium products give 2x credits
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Update user credits - safely access credits field
|
|
39
|
+
const currentCredits = (user as any).credits || 0;
|
|
40
|
+
const newTotalCredits = currentCredits + creditsToAdd;
|
|
41
|
+
|
|
42
|
+
await ctx.db.patch(userId, {
|
|
43
|
+
credits: newTotalCredits,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Log the purchase
|
|
47
|
+
await ctx.db.insert('purchases', {
|
|
48
|
+
userId,
|
|
49
|
+
productId: args.productId,
|
|
50
|
+
quantity: args.quantity,
|
|
51
|
+
creditsAdded: creditsToAdd,
|
|
52
|
+
purchaseDate: Date.now(),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
success: true,
|
|
57
|
+
newCredits: creditsToAdd,
|
|
58
|
+
totalCredits: newTotalCredits,
|
|
59
|
+
};
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get user's current credit balance
|
|
65
|
+
*/
|
|
66
|
+
export const getUserCredits = query({
|
|
67
|
+
args: {},
|
|
68
|
+
returns: v.union(v.number(), v.null()),
|
|
69
|
+
handler: async (ctx) => {
|
|
70
|
+
const userId = await getAuthUserId(ctx);
|
|
71
|
+
if (!userId) {
|
|
72
|
+
throw new Error('Not authenticated');
|
|
73
|
+
}
|
|
74
|
+
const user = await ctx.db.get(userId);
|
|
75
|
+
|
|
76
|
+
return (user as any)?.credits || 0;
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get user's purchase history with pagination
|
|
82
|
+
*/
|
|
83
|
+
export const getPurchaseHistory = query({
|
|
84
|
+
args: {
|
|
85
|
+
paginationOpts: v.optional(
|
|
86
|
+
v.object({
|
|
87
|
+
numItems: v.number(),
|
|
88
|
+
cursor: v.union(v.string(), v.null()),
|
|
89
|
+
}),
|
|
90
|
+
),
|
|
91
|
+
},
|
|
92
|
+
returns: v.object({
|
|
93
|
+
page: v.array(
|
|
94
|
+
v.object({
|
|
95
|
+
_id: v.id('purchases'),
|
|
96
|
+
_creationTime: v.number(),
|
|
97
|
+
productId: v.string(),
|
|
98
|
+
quantity: v.number(),
|
|
99
|
+
creditsAdded: v.number(),
|
|
100
|
+
purchaseDate: v.number(),
|
|
101
|
+
}),
|
|
102
|
+
),
|
|
103
|
+
isDone: v.boolean(),
|
|
104
|
+
continueCursor: v.string(),
|
|
105
|
+
pageStatus: v.optional(v.union(v.string(), v.null())),
|
|
106
|
+
splitCursor: v.optional(v.union(v.string(), v.null())),
|
|
107
|
+
}),
|
|
108
|
+
handler: async (ctx, args) => {
|
|
109
|
+
const userId = await getAuthUserId(ctx);
|
|
110
|
+
if (!userId) {
|
|
111
|
+
throw new Error('Not authenticated');
|
|
112
|
+
}
|
|
113
|
+
return await ctx.db
|
|
114
|
+
.query('purchases')
|
|
115
|
+
.withIndex('by_userId', (q) => q.eq('userId', userId))
|
|
116
|
+
.order('desc')
|
|
117
|
+
.paginate(args.paginationOpts ?? { numItems: 50, cursor: null });
|
|
118
|
+
},
|
|
119
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payments",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "In-app purchases and subscriptions with RevenueCat",
|
|
5
5
|
"copy": [
|
|
6
6
|
{
|
|
@@ -10,6 +10,18 @@
|
|
|
10
10
|
{
|
|
11
11
|
"from": "apps/native/src/features/payments",
|
|
12
12
|
"to": "apps/native/src/features/payments"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"from": "apps/native/src/api-client/payments.ts",
|
|
16
|
+
"to": "apps/native/src/api-client/payments.ts"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"from": "packages/backend/convex/payments",
|
|
20
|
+
"to": "packages/backend/convex/payments"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"from": "packages/backend/convex/payments.ts",
|
|
24
|
+
"to": "packages/backend/convex/payments.ts"
|
|
13
25
|
}
|
|
14
26
|
],
|
|
15
27
|
"nav": {
|
|
@@ -21,7 +33,8 @@
|
|
|
21
33
|
"target": "native",
|
|
22
34
|
"dependencies": {
|
|
23
35
|
"expo": [
|
|
24
|
-
"react-native-purchases"
|
|
36
|
+
"react-native-purchases",
|
|
37
|
+
"react-native-purchases-ui"
|
|
25
38
|
]
|
|
26
39
|
},
|
|
27
40
|
"env": [
|
|
Binary file
|
package/recipes/quiz/recipe.json
CHANGED
package/recipes/quiz@latest.zip
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/commands/add.ts
CHANGED
|
@@ -22,7 +22,8 @@ import {
|
|
|
22
22
|
ENV_CONSTANTS_END,
|
|
23
23
|
ENV_CONSTANTS_START,
|
|
24
24
|
} from '../core/codemod.js';
|
|
25
|
-
import { join, resolve } from 'path';
|
|
25
|
+
import { join, resolve, dirname } from 'path';
|
|
26
|
+
import { copyFile, mkdir } from 'fs/promises';
|
|
26
27
|
import { ensureWithinBase } from '../core/pathGuard.js';
|
|
27
28
|
import { extractZipSafe } from '../core/archive.js';
|
|
28
29
|
import { hashFiles } from '../core/hash.js';
|
|
@@ -259,6 +260,41 @@ function groupEnvVars(env: RecipeManifest['env'] | undefined, cwd: string): EnvG
|
|
|
259
260
|
return [...groups.values()];
|
|
260
261
|
}
|
|
261
262
|
|
|
263
|
+
async function ensureEnvFileFromExample(
|
|
264
|
+
group: EnvGroup,
|
|
265
|
+
options: any,
|
|
266
|
+
): Promise<boolean> {
|
|
267
|
+
if (await exists(group.path)) {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const exampleCandidates = [
|
|
272
|
+
`${group.path}.example`,
|
|
273
|
+
join(dirname(group.path), '.env.example'),
|
|
274
|
+
];
|
|
275
|
+
const examplePath = (await Promise.all(
|
|
276
|
+
exampleCandidates.map(async (candidate) => ((await exists(candidate)) ? candidate : null)),
|
|
277
|
+
)).find(Boolean);
|
|
278
|
+
|
|
279
|
+
if (!examplePath) {
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const exampleLabel = examplePath.startsWith(dirname(group.path))
|
|
284
|
+
? examplePath.slice(dirname(group.path).length + 1)
|
|
285
|
+
: examplePath;
|
|
286
|
+
|
|
287
|
+
if (options?.dryRun) {
|
|
288
|
+
log.info(`[DRY RUN] Would create ${group.relativePath} from ${exampleLabel}`);
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
await mkdir(dirname(group.path), { recursive: true });
|
|
293
|
+
await copyFile(examplePath, group.path);
|
|
294
|
+
log.info(`Created ${group.relativePath} from ${exampleLabel}`);
|
|
295
|
+
return true;
|
|
296
|
+
}
|
|
297
|
+
|
|
262
298
|
async function ensureEnvVarsForGroups(
|
|
263
299
|
envGroups: EnvGroup[],
|
|
264
300
|
options: any,
|
|
@@ -266,6 +302,8 @@ async function ensureEnvVarsForGroups(
|
|
|
266
302
|
const summary: Array<{ relativePath: string; added: string[] }> = [];
|
|
267
303
|
|
|
268
304
|
for (const group of envGroups) {
|
|
305
|
+
await ensureEnvFileFromExample(group, options);
|
|
306
|
+
|
|
269
307
|
const vars: CoreEnvVar[] = group.vars.map(envVar => ({
|
|
270
308
|
key: envVar.key,
|
|
271
309
|
value: envVar.value ?? envVar.example ?? '',
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/recipes/voice-bot/apps/native/src/app/{voice-bot → (root)/(protected)/voice-bot}/index.tsx
RENAMED
|
File without changes
|