@l4yercak3/cli 1.2.18 → 1.2.20
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/.claude/settings.local.json +3 -1
- package/docs/CRM-PIPELINES-SEQUENCES-SPEC.md +429 -0
- package/package.json +1 -1
- package/src/commands/login.js +26 -7
- package/src/commands/spread.js +150 -4
- package/src/detectors/expo-detector.js +4 -4
- package/src/generators/env-generator.js +23 -8
- package/src/generators/expo-auth-generator.js +1009 -0
- package/src/generators/quickstart/components-mobile/index.js +1440 -0
- package/src/generators/quickstart/hooks/index.js +23 -5
- package/src/generators/quickstart/index.js +44 -10
- package/src/generators/quickstart/screens/index.js +1498 -0
- package/tests/expo-detector.test.js +3 -4
|
@@ -13,17 +13,35 @@ class HooksGenerator {
|
|
|
13
13
|
* @param {Object} options - Generation options
|
|
14
14
|
* @returns {Promise<Object>} - Generated file paths
|
|
15
15
|
*/
|
|
16
|
+
/**
|
|
17
|
+
* Check if framework is Expo/React Native
|
|
18
|
+
*/
|
|
19
|
+
isMobileFramework(frameworkType) {
|
|
20
|
+
return ['expo', 'react-native'].includes(frameworkType);
|
|
21
|
+
}
|
|
22
|
+
|
|
16
23
|
async generate(options) {
|
|
17
|
-
const { projectPath, features = [] } = options;
|
|
24
|
+
const { projectPath, features = [], frameworkType } = options;
|
|
25
|
+
const isMobile = this.isMobileFramework(frameworkType);
|
|
18
26
|
|
|
19
27
|
const results = {};
|
|
20
28
|
|
|
21
|
-
// Determine output directory
|
|
29
|
+
// Determine output directory based on framework
|
|
22
30
|
let outputDir;
|
|
23
|
-
if (
|
|
24
|
-
|
|
31
|
+
if (isMobile) {
|
|
32
|
+
// Expo typically uses src/lib or just lib
|
|
33
|
+
if (fs.existsSync(path.join(projectPath, 'src'))) {
|
|
34
|
+
outputDir = path.join(projectPath, 'src', 'lib', 'l4yercak3', 'hooks');
|
|
35
|
+
} else {
|
|
36
|
+
outputDir = path.join(projectPath, 'lib', 'l4yercak3', 'hooks');
|
|
37
|
+
}
|
|
25
38
|
} else {
|
|
26
|
-
|
|
39
|
+
// Next.js uses src/lib
|
|
40
|
+
if (fs.existsSync(path.join(projectPath, 'src'))) {
|
|
41
|
+
outputDir = path.join(projectPath, 'src', 'lib', 'l4yercak3', 'hooks');
|
|
42
|
+
} else {
|
|
43
|
+
outputDir = path.join(projectPath, 'lib', 'l4yercak3', 'hooks');
|
|
44
|
+
}
|
|
27
45
|
}
|
|
28
46
|
|
|
29
47
|
ensureDir(outputDir);
|
|
@@ -6,10 +6,13 @@
|
|
|
6
6
|
const databaseGenerator = require('./database');
|
|
7
7
|
const hooksGenerator = require('./hooks');
|
|
8
8
|
const componentGenerator = require('./components');
|
|
9
|
+
const mobileComponentGenerator = require('./components-mobile');
|
|
9
10
|
const pageGenerator = require('./pages');
|
|
11
|
+
const screensGenerator = require('./screens');
|
|
10
12
|
const apiOnlyGenerator = require('../api-only');
|
|
11
13
|
const envGenerator = require('../env-generator');
|
|
12
14
|
const nextauthGenerator = require('../nextauth-generator');
|
|
15
|
+
const expoAuthGenerator = require('../expo-auth-generator');
|
|
13
16
|
const oauthGuideGenerator = require('../oauth-guide-generator');
|
|
14
17
|
const gitignoreGenerator = require('../gitignore-generator');
|
|
15
18
|
|
|
@@ -53,9 +56,13 @@ class QuickStartGenerator {
|
|
|
53
56
|
// Pages (Next.js only)
|
|
54
57
|
pages: null,
|
|
55
58
|
|
|
59
|
+
// Screens (Expo only)
|
|
60
|
+
screens: null,
|
|
61
|
+
|
|
56
62
|
// Common files
|
|
57
63
|
envFile: null,
|
|
58
64
|
nextauth: null,
|
|
65
|
+
expoAuth: null,
|
|
59
66
|
oauthGuide: null,
|
|
60
67
|
gitignore: null,
|
|
61
68
|
};
|
|
@@ -64,6 +71,14 @@ class QuickStartGenerator {
|
|
|
64
71
|
const isMobile = this.isMobileFramework(frameworkType);
|
|
65
72
|
const isNextJs = this.isNextJs(frameworkType);
|
|
66
73
|
|
|
74
|
+
// Debug logging
|
|
75
|
+
if (process.env.L4YERCAK3_DEBUG) {
|
|
76
|
+
console.log('\n[DEBUG] QuickStart Generator:');
|
|
77
|
+
console.log(` frameworkType: "${frameworkType}"`);
|
|
78
|
+
console.log(` isMobile: ${isMobile}`);
|
|
79
|
+
console.log(` isNextJs: ${isNextJs}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
67
82
|
// 1. Generate the typed API client package
|
|
68
83
|
const apiOnlyResults = await apiOnlyGenerator.generate(options);
|
|
69
84
|
results.apiClient = apiOnlyResults.client;
|
|
@@ -81,23 +96,35 @@ class QuickStartGenerator {
|
|
|
81
96
|
results.hooks = await hooksGenerator.generate(options);
|
|
82
97
|
}
|
|
83
98
|
|
|
84
|
-
// 4. Generate React components
|
|
99
|
+
// 4. Generate React components (mobile or web)
|
|
85
100
|
if (options.features && options.features.length > 0) {
|
|
86
|
-
|
|
101
|
+
if (isMobile) {
|
|
102
|
+
results.components = await mobileComponentGenerator.generate(options);
|
|
103
|
+
} else {
|
|
104
|
+
results.components = await componentGenerator.generate(options);
|
|
105
|
+
}
|
|
87
106
|
}
|
|
88
107
|
|
|
89
|
-
// 5. Generate pages (Next.js
|
|
90
|
-
if (
|
|
91
|
-
|
|
108
|
+
// 5. Generate pages (Next.js) or screens (Expo)
|
|
109
|
+
if (options.features && options.features.length > 0) {
|
|
110
|
+
if (isNextJs) {
|
|
111
|
+
results.pages = await pageGenerator.generate(options);
|
|
112
|
+
} else if (isMobile) {
|
|
113
|
+
results.screens = await screensGenerator.generate(options);
|
|
114
|
+
}
|
|
92
115
|
}
|
|
93
116
|
|
|
94
117
|
// 6. Generate environment file
|
|
95
118
|
results.envFile = envGenerator.generate(this.enhanceEnvOptions(options));
|
|
96
119
|
|
|
97
|
-
// 7. Generate
|
|
120
|
+
// 7. Generate auth config if OAuth is enabled
|
|
98
121
|
if (options.features && options.features.includes('oauth') && options.oauthProviders) {
|
|
99
122
|
if (isNextJs) {
|
|
123
|
+
// NextAuth.js for Next.js
|
|
100
124
|
results.nextauth = await nextauthGenerator.generate(options);
|
|
125
|
+
} else if (isMobile) {
|
|
126
|
+
// expo-auth-session for Expo/React Native
|
|
127
|
+
results.expoAuth = await expoAuthGenerator.generate(options);
|
|
101
128
|
}
|
|
102
129
|
}
|
|
103
130
|
|
|
@@ -123,15 +150,19 @@ class QuickStartGenerator {
|
|
|
123
150
|
const enhanced = { ...options };
|
|
124
151
|
enhanced.additionalEnvVars = enhanced.additionalEnvVars || [];
|
|
125
152
|
|
|
153
|
+
const isMobile = this.isMobileFramework(options.frameworkType);
|
|
154
|
+
// Use EXPO_PUBLIC_ for Expo, NEXT_PUBLIC_ for Next.js
|
|
155
|
+
const publicPrefix = isMobile ? 'EXPO_PUBLIC_' : 'NEXT_PUBLIC_';
|
|
156
|
+
|
|
126
157
|
if (options.selectedDatabase === 'convex') {
|
|
127
158
|
enhanced.additionalEnvVars.push(
|
|
128
159
|
{ key: 'CONVEX_DEPLOYMENT', value: '', comment: 'Convex deployment URL (from npx convex dev)' },
|
|
129
|
-
{ key:
|
|
160
|
+
{ key: `${publicPrefix}CONVEX_URL`, value: '', comment: 'Convex public URL' }
|
|
130
161
|
);
|
|
131
162
|
} else if (options.selectedDatabase === 'supabase') {
|
|
132
163
|
enhanced.additionalEnvVars.push(
|
|
133
|
-
{ key:
|
|
134
|
-
{ key:
|
|
164
|
+
{ key: `${publicPrefix}SUPABASE_URL`, value: '', comment: 'Supabase project URL' },
|
|
165
|
+
{ key: `${publicPrefix}SUPABASE_ANON_KEY`, value: '', comment: 'Supabase anonymous key' },
|
|
135
166
|
{ key: 'SUPABASE_SERVICE_ROLE_KEY', value: '', comment: 'Supabase service role key (server only)' }
|
|
136
167
|
);
|
|
137
168
|
}
|
|
@@ -140,10 +171,13 @@ class QuickStartGenerator {
|
|
|
140
171
|
enhanced.additionalEnvVars.push(
|
|
141
172
|
{ key: 'STRIPE_SECRET_KEY', value: '', comment: 'Stripe secret key' },
|
|
142
173
|
{ key: 'STRIPE_WEBHOOK_SECRET', value: '', comment: 'Stripe webhook signing secret' },
|
|
143
|
-
{ key:
|
|
174
|
+
{ key: `${publicPrefix}STRIPE_PUBLISHABLE_KEY`, value: '', comment: 'Stripe publishable key' }
|
|
144
175
|
);
|
|
145
176
|
}
|
|
146
177
|
|
|
178
|
+
// Pass mobile flag to env generator
|
|
179
|
+
enhanced.isMobile = isMobile;
|
|
180
|
+
|
|
147
181
|
return enhanced;
|
|
148
182
|
}
|
|
149
183
|
}
|